补充
函数类型
function greeter(fn: (a: string) => void) {
fn("Hello, World");
}
function printToConsole(s: string) {
console.log(s);
}
greeter(printToConsole);
可选参数
function f(x?: number) {
// ...
}
构造函数
interface CallOrConstruct {
new (s: string): Date;
(n?: number): string;
}
function fn(ctor: CallOrConstruct) {
return new ctor("hello");
// 或者返回不带new 的属性
// return ctor(1);
}
添加泛型作为类型参数
function firstElement<Type>(arr: Type[]): Type | undefined {
return arr[0];
}
合理使用length属性
function longest<Type extends { length: number }>(a: Type, b: Type) {
if (a.length >= b.length) {
return a;
} else {
return b;
}
}
rest更多参数
function multiply(n: number, ...m: number[]) {
return m.map((x) => n * x);
}
// 'a' gets value [10, 20, 30, 40]
const a = multiply(10, 1, 2, 3, 4);
数组类型
ReadonlyArray数组属性是只读的
function doStuff(values: ReadonlyArray<string>) {
// We can read from 'values'...
const copy = values.slice();
console.log(`The first value is ${values[0]}`);
// ...but we can't mutate 'values'.
values.push("hello!"); // Property 'push' does not exist on type 'readonly string[]'.
// 直接修改数组可以,但不能直接修改属性
values = ['abc']; // ok
}
// 报错:'ReadonlyArray' only refers to a type, but is being used as a value here.
new ReadonlyArray("red", "green", "blue");
readonly数组属性是只读的
function doStuff(values: readonly string[]) {
// We can read from 'values'...
const copy = values.slice();
console.log(`The first value is ${values[0]}`);
// ...but we can't mutate 'values'.
values.push("hello!"); // Error: Property 'push' does not exist on type 'readonly string[]'.
}
let x: readonly string[] = [];
let y: string[] = [];
x = y; // 直接赋值数组可以
x[0]='1'; // Error: 直接修数组属性不行
y = x; // Error: 只读属性不能分配给string[]可变属性
对象类型
使用type别名
type Person = {
name: string;
age: number;
};
使用interface接口
interface Person {
name: string;
age: number;
}
可选属性
interface SquareConfig {
color: string;
width?: number;
}
只读属性
interface SomeType {
readonly prop: string;
}
type SomeType2 = {
readonly prop: string;
}
只定义属性名类型,不定义具体属性名
interface StringArray {
[index: number]: string;
}
interface NumberDictionary {
[index: string]: number;
length: number; // ok
name: string; // Property 'name' of type 'string' is not assignable to 'string' index type 'number'.
}
interface NumberOrStringDictionary {
[index: string]: number | string;
length: number; // ok, length is a number
name: string; // ok, name is a string
}
interface ReadonlyStringArray {
readonly [index: number]: string;
}
interface SquareConfig {
color?: string;
width?: number;
[propName: string]: any;
}
extends扩展属性
interface AddressWithUnit extends BasicAddress {
unit: string;
}
// 扩展多个
interface Colorful {
color: string;
}
interface Circle {
radius: number;
}
interface ColorfulCircle extends Colorful, Circle {}
const cc: ColorfulCircle = {
color: "red",
radius: 42,
};
由类型生成新类型
1.使用泛型
函数中的类型参数
function identity<Type>(arg: Type): Type {
return arg;
}
let myIdentity: <Type>(arg: Type) => Type = identity;
// 泛型接口
interface GenericIdentityFn<Type> {
(arg: Type): Type;
}
function identity<Type>(arg: Type): Type {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
class中使用泛型
class GenericNumber<NumType> {
zeroValue: NumType;
add: (x: NumType, y: NumType) => NumType;
}
泛型中使用extends
function createInstance<A extends Animal>(c: new () => A): A {
return new c();
}
2.keyof获取属性名类型组成联合类型
type Arrayish = { [n: number]: unknown };
type A = keyof Arrayish; // number
3.typeof获取返回值类型组成联合类型
let s = "hello";
let n: typeof s; // string
3.索引类型
对象的索引
type Person = { age: number; name: string; alive: boolean };
// 单索引
type Age = Person["age"]; // number
// 多索引 - 联合类型
type I1 = Person["age" | "name"]; // string | number
type AliveOrName = "alive" | "name";
type I3 = Person[AliveOrName]; // boolean | string
// 多索引 - keyof
type I2 = Person[keyof Person]; // string | number | boolean
数组的索引
const MyArray = [
{ name: "Alice", age: 15 },
{ name: "Bob", age: 23 },
{ name: "Eve", age: 38 },
];
// Array[number]在ts中表示数组元素;typeof获取类型的返回值
type Person = typeof MyArray[number]; // { name: string; age: number; }
type Age = typeof MyArray[number]["age"]; // number
type Age2 = Person["age"]; // number
4.条件类型
interface Animal {
live(): void;
}
interface Dog extends Animal {
woof(): void;
}
type Example1 = Dog extends Animal ? number : string; // number
type Example2 = RegExp extends Animal ? number : string; // string
条件类型中使用infer类型推断
type Flatten<Type> = Type extends Array<infer Item> ? Item : Type;
type GetReturnType<Type> = Type extends (...args: never[]) => infer Return
? Return
: never;
type Num = GetReturnType<() => number>; // number
type Str = GetReturnType<(x: string) => string>; // string
type Bools = GetReturnType<(a: boolean, b: boolean) => boolean[]>; // boolean[]
5.映射类型
索引签名用于声明尚未提前声明的属性类型
type OnlyBoolsAndHorses = {
[key: string]: boolean | Horse;
};
const conforms: OnlyBoolsAndHorses = {
del: true,
rodney: false,
};
泛型
type OptionsFlags<Type> = {
[Property in keyof Type]: boolean;
};
移除属性的只读状态(-readonly)
type CreateMutable<Type> = {
-readonly [Property in keyof Type]: Type[Property];
};
type LockedAccount = {
readonly id: string;
readonly name: string;
};
type UnlockedAccount = CreateMutable<LockedAccount>; // { id: string, name: string }
移除属性的可选状态(-?)
type Concrete<Type> = {
[Property in keyof Type]-?: Type[Property];
};
type MaybeUser = {
id: string;
name?: string;
age?: number;
};
type User = Concrete<MaybeUser>; // { id: string;name: string;age: number; }
使用as重写属性名
type Getters<Type> = {
[Property in keyof Type as `get${Capitalize<string & Property>}`]: () => Type[Property]
};
interface Person {
name: string;
age: number;
location: string;
}
type LazyPerson = Getters<Person>; // { getName: () => string;getAge: () => number;getLocation: () => string; }
使用as+Exclude过滤属性
type RemoveKindField<Type> = {
[Property in keyof Type as Exclude<Property, "kind">]: Type[Property]
};
interface Circle {
kind: "circle";
radius: number;
}
type KindlessCircle = RemoveKindField<Circle>; // { radius: number; }
使用as+索引类型重写属性名
type EventConfig<Events extends { kind: string }> = {
[E in Events as E["kind"]]: (event: E) => void;
}
type SquareEvent = { kind: "square", x: number, y: number };
type CircleEvent = { kind: "circle", radius: number };
type Config = EventConfig<SquareEvent | CircleEvent> // { square: (event: SquareEvent) => void; cirle: (event: CircleEvent) => void;}
6.使用模板字符串
字符串
type World = "world";
type Greeting = `hello ${World}`; // "hello world"
字符串组成的联合类型
type EmailLocaleIDs = "welcome_email" | "email_heading";
type FooterLocaleIDs = "footer_title" | "footer_sendoff";
type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`; // "welcome_email_id" | "email_heading_id" | "footer_title_id" | "footer_sendoff_id"
type Lang = "en" | "ja" | "pt";
type LocaleMessageIDs = `${Lang}_${AllLocaleIDs}`; // "en_welcome_email_id" | "en_email_heading_id" | "en_footer_title_id" | "en_footer_sendoff_id" | "ja_welcome_email_id" | "ja_email_heading_id" | "ja_footer_title_id" | "ja_footer_sendoff_id" | "pt_welcome_email_id" | "pt_email_heading_id" | "pt_footer_title_id" | "pt_footer_sendoff_id"
7.类型工具
Record<K, T>
: 创建一个以类型K
为键,类型T
为值的对象类型。Readonly<T>
: 创建只读版本的类型。Partial<T>
: 复制T
类型的所有属性,并将所有属变成可选属性Required<T>
: 复制T
类型的所有属性,并将所有属变成必选属性Pick<T, K>
: 子集,从类型T
中选取指定属性K
。Omit<T, K>
: 排除,从类型T
中排除属性K
。Exclude<T, U>
: 从类型T
中排除可以赋值给类型U
的类型。ReturnType<T>
: 获取函数类型T
的返回类型。Union
: 用于创建联合类型,例如 number | string。或
的关系Intersection
: 用于创建交叉类型,表示同时具有多个类型的值。且
的关系
8.字符串操作类型
Uppercase
: 转大写Lowercase
: 转小写Capitalize
: 首字母转大写Uncapitalize
: 首字母转小写
重载函数
重载版本的函数签名
- 函数体之前的,每个版本对应不同的参数和返回值类型
- 最后的通用实现部分(即函数体)必须能够处理所有可能的参数类型,通常使用联合类型或条件类型来实现
- 用于处理一些复杂的情况,例如函数根据传递的参数类型来决定不同的逻辑。它们能够提供更好的类型检查和类型推断,从而增加代码的安全性和可读性
function greet(name: string): string;
function greet(age: number): string;
function greet(input: string | number): string {
if (typeof input === "string") {
return `Hello, ${input}!`;
} else if (typeof input === "number") {
return `You are ${input} years old.`;
}
return "Hello!";
}
console.log(greet("Alice")); // Hello, Alice!
console.log(greet(25)); // You are 25 years old.
console.log(greet(true)); // Error: Argument of type 'boolean' is not assignable to parameter of type 'string | number'.
其它
1.Parameters
用于从函数类型中获取参数类型的元组类型
type MyFunction = (a: number, b: string, c: boolean) => void;
type MyFunctionParameters = Parameters<MyFunction>; // [number, string, boolean]
2.const类型断言中的字面量类型
const myNumber = 42;
const myLiteralNumber = 42 as const; // 类型为 42(数字字面量类型)
const myString = "hello";
const myLiteralString = "hello" as const; // 类型为 "hello"(字符串字面量类型)