通用类型
一个简单的函数
function func<T>(data: T): T {
return data;
}
const val = func<string>('hello');
const val1 = func('hello');
在通用约束中使用类型参数
你可以声明类型参数来约束其他类型参数。例如:
function getValue<Type, Key extends keyof Type>(obj: Type, key: Key) {
return obj[key];
}
let x = { a: 1, b: 2, c: 3, d: 4 };
getProperty(x, 'a');
getProperty(x, 'm');
keyof 类型操作
type obj = { test: 'test'; str: 'str' };
type key = keyof obj;
const keys: key = 'a';
const keys: key = 'test';
typeof 类型操作
typeof 可以返回参数的类型
let h = 'hello';
type t = typeof h;
ReturnType 可以返回函数返回的类型,例如:
type func = () => boolean;
type funcType = ReturnType<func>;
const f = () => { a: 1, b: 2 }
type fType = ReturnType<typeof f>
索引允许值
type Person = { age: number; name: string; alive: boolean };
type Age = Person['age'];
type T1 = Person['age' | 'name'];
条件类型
条件类型于三目运算符类似,表达式如下:
someType extends OtherType ? TrueType : FalseType
文字表达如下:如果一个类型继承于某个其他类型,则为 true,否则 false
For Instance:
interface Animal {
live(): void;
}
interface Dog extends Animal {
woof(): void;
}
type Example1 = Dog extends Animal ? number : string;
type Example2 = RegExp extends Animal ? number : string;
有时候我们需要根据输入类型的不同而返回对应的类型,例如以下这个函数:
interface IdType = {
id: number
}
interface NameType = {
name: string
}
function createLabel(id: number): IdType;
function createLabel(name: string): NameType;
function createLabel(idOrName: number | string): IdType | NameType ;
function createLabel(idOrName: number | string): IdType | NameType {
}
上面例子通过重载,根据参数的不同类型,返回不同的数据,可以看出函数非常复杂。这里可以使用条件类型替换他:
interface IdType = {
id: number
}
interface NameType = {
name: string
}
type IdOrName<T extends string | number> = T extends string ? NameType : IdType
function createLabel<T extends string | number>(key: T): IdOrName<T> {
}
条件类型约束
type MessageOf<T> = T['message'];
上面例子中,泛型 T 不知道是否有一个叫 message 的属性,所以报错了,我们必须约束泛型 T,让他能支持 message 这个属性:
type MessageOf<T extends { message: unknown }> = T['message'];
interface Email {
message: string;
}
type EmailMessageContents = MessageOf<Email>;
如果属性中没有message这个属性,则需要返回 never,这时我们可以使用条件类型取约束
type MessageOf<T> = T extends { message: unknown } ? T['message'] : never;
interface Email {
message: string;
}
interface Dog {
bark(): void;
}
type EmailMessageContents = MessageOf<Email>;
type DogMessageContents = MessageOf<Dog>;
推断中使用条件类型
type Flatten<Type> = Type extends Array<infer Item> ? Item : Type;
type T1 = Flatten<string[]>;
type T2 = Flatten<number>;
type GetReturnType<Type> = Type extends (...args: never[]) => infer Return
? Return
: never;
type Num = GetReturnType<() => number>;
type Str = GetReturnType<(x: string) => string>;
type Bools = GetReturnType<(a: boolean, b: boolean) => boolean[]>;
分配式的条件类型
When conditional types act on a generic type, they become distributive when given a union type
当条件类型用作分配时,他们会使联合类型变得可分配????看不懂,直接上代码
type ToArray<Type> = Type extends any ? Type[] : never;
type T1 = ToArray<string | number>; // type T1 = string[] | number[]
type ToArrayNonDist<Type> = [Type] extends [any] ? Type[] : never; // type StrArrOrNumArr = ToArrayNonDist<string | number>;
映射类型
当你不想做重复的工作,有时候类型需要基于一些其他类型
映射类型用于声明未提前声明的属性类型, For Example:
type T = {
[key: string]: string | number;
};
const test: T = {
test1: 'hello',
test2: 1234,
};
映射类型是一种通用类型,也可以配合keyof使用去创建一些类型
type Type = {
test1: string;
test2: number;
};
type Type2<T> = {s
[key in keyof T]: boolean;
};
type Rest = Type2<Type>
映射修改
当我我们添加映射时,有两个额外的操作符可以修改:readonly 和 ?
type CreateType<Type> = {
-readonly [Key in keyof Type]: Type[Key];
};
type LockType = {
readonly test1: string;
readonly test2: string;
};
type UnLockType = CreateType<LockType>;
type CreateMustType<Type> = {
[Key in keyof Type]-?: Type[Key];
};
type maybeType = {
test1?: string;
test2?: string;
};
type MustType = CreateMustType<maybeType>;
Key 的重映射
在 Typescript 4.1中,你可以用as来重新定义映射名。
语法:
type RemapType<Type> = {
[Key in keyof Type as newKey]: Type[Key];
};
例如:
type AddGetName<Type> = {
[Key in keyof Type as `get${Capitalize<string & Key>}`]: Type[Key];
};
type TestType = {
test1: string;
test2: string;
};
type AddTestType = AddGetName<TestType>;
模板文字类型
与 es6 模板字符串类似
type Type1 = 'World';
type Hello = `Hello ${Type1}`;