1. typeof 操作符(类型查询操作符) 功能 从 JavaScript 值中提取类型信息,获取变量、函数、对象等的类型。
定义实现 type TypeOfResult = typeof someValue;
使用案例 const num = 42 ;type NumType = typeof num; const str = "hello" ;type StrType = typeof str; const config = { apiUrl : "https://api.example.com" , timeout : 5000 , retries : 3 }; type ConfigType = typeof config;function add (a : number , b : number ): number { return a + b; } type AddFunctionType = typeof add;class User { constructor (public name : string , public age : number ) {} } type UserConstructor = typeof User ;const api = { users : { getAll : () => Promise <User []>, getById : (id : string ) => Promise <User > }, posts : { create : (data : any ) => Promise <void > } }; type ApiType = typeof api;
错误场景 type MyType = { name : string };type WrongUsage = typeof MyType ; type AnotherWrong = typeof string ; const myValue : MyType = { name : "test" };type CorrectUsage = typeof myValue;
2. keyof 操作符(键查询操作符) 功能 获取对象类型所有键的联合类型。
定义实现 type KeysOf <T> = keyof T;
使用案例 interface Person { name : string ; age : number ; email : string ; } type PersonKeys = keyof Person ; type ArrayKeys = keyof string []; type StringKeys = keyof string ; function getProperty<T, K extends keyof T>(obj : T, key : K): T[K] { return obj[key]; } const person : Person = { name : "Alice" , age : 30 , email : "alice@example.com" };const name = getProperty (person, "name" ); const age = getProperty (person, "age" ); type DynamicKeys = keyof { [key : string ]: any }; type Optional <T> = { [K in keyof T]?: T[K]; }; type OptionalPerson = Optional <Person >;
错误场景 const obj = { a : 1 , b : 2 };type Wrong = keyof obj; type Correct = keyof typeof obj; type PrimitiveKeys = keyof number ; type NeverKeys = keyof never ;
3. extends 操作符(条件类型操作符) 功能 用于条件类型判断和泛型约束,判断一个类型是否可以赋值给另一个类型。也可以理解为,判断前者是否是后者的子类型,比如“a”就是string的子类型。
为泛型做类型限制
类的继承
三元运算符(子类型判断)
定义实现 type Conditional <T, U, X, Y> = T extends U ? X : Y;type Constrained <T extends SomeType > = T;
使用案例 type IsString <T> = T extends string ? true : false ;type Test1 = IsString <string >; type Test2 = IsString <number >; interface Lengthwise { length : number ; } function loggingIdentity<T extends Lengthwise >(arg : T): T { console .log (arg.length ); return arg; } function cpmpare<T extends {length : number }>(a :T, b :T){ return a.length >= b.length ? a : b; } type NonNullable <T> = T extends null | undefined ? never : T;type Result = NonNullable <string | null | undefined >; type ToArray <T> = T extends any ? T[] : never ;type Arrays = ToArray <string | number >; type DeepReadonly <T> = { readonly [P in keyof T]: T[P] extends object ? T[P] extends Function ? T[P] : DeepReadonly <T[P]> : T[P]; }; type FilterByType <T, U> = { [K in keyof T]: T[K] extends U ? K : never ; }[keyof T]; interface Mixed { name : string ; age : number ; isActive : boolean ; callback : () => void ; } type StringKeys = FilterByType <Mixed , string >; type FunctionKeys = FilterByType <Mixed , Function >;
错误场景 const value = "hello" ;type Wrong = value extends string ? true : false ; type BadSyntax <T> = T extends string ; type SelfReferencing <T extends T> = T; type Correct <T> = T extends string ? true : false ;type CorrectConstraint <T extends string > = T;
分布式条件类型vs非分布式类型参数
type Distributive <T> = T extends 'a' ? 'yes' : 'no' ;type Result1 = Distributive <'a' | 'b' | 'c' >; type NonDistributive = 'a' | 'b' | 'c' extends 'a' ? 'yes' : 'no' ; type PreventDistribution <T> = [T] extends ['a' ] ? 'yes' : 'no' ;type Result3 = PreventDistribution <'a' | 'b' | 'c' >;
4. infer 操作符(类型推断操作符) 功能 在条件类型中推断类型,只能在条件类型的 extends 子句中使用。可以类比设参数列方程,只不过ts自动帮我们解方程。
定义实现 type InferExample <T> = T extends SomeType <infer U> ? U : never ;
使用案例 type MyReturnType <T> = T extends (...args : any []) => infer R ? R : never ;type FuncReturn = MyReturnType <() => string >; type FuncReturn2 = MyReturnType <(x : number ) => boolean >; type FirstParameter <T> = T extends (first : infer P, ...args : any []) => any ? P : never ;type FirstParam = FirstParameter <(a : string , b : number ) => void >; type ArrayElement <T> = T extends (infer U)[] ? U : never ;type Element = ArrayElement <string []>; type MyAwaited <T> = T extends Promise <infer K> ? K extends Promise <any > ? MyAwaited <K> : K : unknown ; type Resolved = MyAwaited <Promise <string >>; type PropertyType <T, K extends keyof T> = T extends { [P in K]: infer V } ? V : never ;interface User { name : string ; age : number ; } type NameType = PropertyType <User , "name" >; type Head <T> = T extends [infer H, ...any []] ? H : never ;type Tail <T> = T extends [any , ...infer T] ? T : never ;type HeadResult = Head <[string , number , boolean ]>; type TailResult = Tail <[string , number , boolean ]>; type ConstructorParameters <T> = T extends new (...args : infer P) => any ? P : never ;class MyClass { constructor (name : string , age : number ) {} } type MyClassParams = ConstructorParameters <typeof MyClass >;
错误场景 type Wrong <T> = infer U; type AlsoWrong <T> = T extends string ? infer U : never ; type Duplicate <T> = T extends [infer U, infer U] ? U : never ; type Correct <T> = T extends [infer U, infer V] ? [U, V] : never ;type CorrectUsage <T> = T extends (...args : any []) => infer R ? R : never ;
5. in 操作符(映射类型操作符) 功能 在映射类型中遍历联合类型的每个成员,创建新的对象类型。
定义实现 type MappedType <T> = { [K in keyof T]: T[K]; };
使用案例 type MyPartial <T> = { [P in keyof T]?: T[P]; }; interface User { name : string ; age : number ; } type PartialUser = MyPartial <User >; type StringKeys = "name" | "age" | "email" ;type StringObject = { [K in StringKeys ]: string ; }; type MyReadonly <T> = { readonly [P in keyof T]: T[P]; }; type ReadonlyUser = MyReadonly <User >; type Mutable <T> = { -readonly [P in keyof T]: T[P]; }; type Required <T> = { [P in keyof T]-?: T[P]; }; type NullableKeys <T> = { [K in keyof T]: T[K] extends null ? K : never ; }[keyof T]; interface Mixed { name : string ; age : number | null ; email : string | null ; } type NullableFields = NullableKeys <Mixed >; type ApiResponse <T> = { [K in keyof T]: { data : T[K]; loading : boolean ; error : string | null ; }; }; interface UserData { profile : User ; posts : Post []; } type UserApiState = ApiResponse <UserData >;
错误场景 type Wrong = "name" in User ; type BadSyntax <T> = { [K in T]: string ; }; type MapNumber = { [K in number ]: string ; }; type Correct <T> = { [K in keyof T]: T[K]; };
6. as 操作符(键重映射操作符) 功能 在映射类型中重新映射键名,可以改变属性名称。
定义实现 type RemappedType <T> = { [K in keyof T as `new_${string & K} ` ]: T[K]; };
使用案例 type Getters <T> = { [K in keyof T as `get${Capitalize<string & K>} ` ]: () => T[K]; }; interface User { name : string ; age : number ; } type UserGetters = Getters <User >;type PickByType <T, U> = { [K in keyof T as T[K] extends U ? K : never ]: T[K]; }; interface Mixed { name : string ; age : number ; isActive : boolean ; callback : () => void ; } type StringProps = PickByType <Mixed , string >; type FunctionProps = PickByType <Mixed , Function >; type EventHandlers <T> = { [K in keyof T as `on${Capitalize<string & K>} Changed` ]: (value : T[K] ) => void ; }; type UserEventHandlers = EventHandlers <User >;type NonFunctionPropertyNames <T> = { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]; type NonFunctionProperties <T> = { [K in NonFunctionPropertyNames <T>]: T[K]; }; type FormState <T> = { [K in keyof T as `${string & K} State` ]: { value : T[K]; error : string | null ; touched : boolean ; }; }; interface LoginForm { username : string ; password : string ; } type LoginFormState = FormState <LoginForm >;
错误场景 type Wrong = string as number ; type BadSyntax <T> = { [K in keyof T]: T[K] as string ; }; type InvalidKey <T> = { [K in keyof T as T[K]]: string ; }; type Correct <T> = { [K in keyof T as `prefix_${string & K} ` ]: T[K]; };
7. [] 操作符(索引访问操作符) 功能 通过索引获取对象类型的属性类型或数组类型的元素类型。
定义实现 type IndexAccess <T, K extends keyof T> = T[K];
使用案例 interface Person { name : string ; age : number ; address : { city : string ; country : string ; }; } type Name = Person ["name" ]; type Age = Person ["age" ]; type Address = Person ["address" ]; type City = Person ["address" ]["city" ]; type StringArray = string [];type ArrayElement = StringArray [number ]; type Tuple = [string , number , boolean ];type First = Tuple [0 ]; type Second = Tuple [1 ]; type Third = Tuple [2 ]; type NameOrAge = Person ["name" | "age" ]; type AllPersonValues = Person [keyof Person ]; type DeepGet <T, K extends string > = K extends `${infer Key} .${infer Rest} ` ? Key extends keyof T ? DeepGet <T[Key ], Rest > : never : K extends keyof T ? T[K] : never ; type DeepCity = DeepGet <Person , "address.city" >; type ArrayElementType <T> = T extends (infer U)[] ? U : never ;type ElementType = ArrayElementType <Person []>; type Parameters <T> = T extends (...args : infer P) => any ? P : never ;type FunctionParams = Parameters <(a : string , b : number ) => void >; type FirstParam = FunctionParams [0 ];
错误场景 type Wrong = Person ["nonExistent" ]; type AlsoWrong = Person [123 ]; type BadIndex = string ["length" ]; const key = "name" ;type DynamicWrong = Person [key]; type Correct = Person ["name" ];type CorrectUnion = Person ["name" | "age" ];type CorrectDynamic <K extends keyof Person > = Person [K];
8. | 操作符(联合类型操作符) 功能 创建联合类型,表示一个值可以是多种类型中的任意一种。
定义实现 type Union <T, U> = T | U;
使用案例 type StringOrNumber = string | number ;type Status = "loading" | "success" | "error" ;function process (value : string | number ): string { if (typeof value === "string" ) { return value.toUpperCase (); } else { return value.toString (); } } type Circle = { kind : "circle" ; radius : number ; }; type Rectangle = { kind : "rectangle" ; width : number ; height : number ; }; type Shape = Circle | Rectangle ;function getArea (shape : Shape ): number { switch (shape.kind ) { case "circle" : return Math .PI * shape.radius ** 2 ; case "rectangle" : return shape.width * shape.height ; } } type ToArray <T> = T extends any ? T[] : never ;type Result = ToArray <string | number >; type ApiResponse <T> = | { success : true ; data : T } | { success : false ; error : string }; type UserResponse = ApiResponse <User >;type Extract <T, U> = T extends U ? T : never ;type StringFromUnion = Extract <string | number | boolean , string >; type Exclude <T, U> = T extends U ? never : T;type NonString = Exclude <string | number | boolean , string >;
错误场景 type Union = { a : string } | { b : number };type Wrong = Union ["a" ]; function badGuard (value : string | number ) { return value.toUpperCase (); } function goodGuard (value : string | number ): string { if (typeof value === "string" ) { return value.toUpperCase (); } return value.toString (); } type CommonUnion = { common : string ; a : number } | { common : string ; b : boolean };type Common = CommonUnion ["common" ];
9. & 操作符(交叉类型操作符) 功能 创建交叉类型,将多个类型合并为一个类型,包含所有类型的属性。
定义实现 type Intersection <T, U> = T & U;
使用案例 type Person = { name : string ; age : number ; }; type Employee = { id : number ; department : string ; }; type PersonEmployee = Person & Employee ;type Logger = { log : (message : string ) => void ; }; type Counter = { count : number ; increment : () => void ; }; type LoggerCounter = Logger & Counter ;const loggerCounter : LoggerCounter = { log : (message ) => console .log (message), count : 0 , increment ( ) { this .count ++; this .log (`Count is now ${this .count} ` ); } }; type Timestamped = { timestamp : Date ; }; type Versioned = { version : number ; }; type Document = { title : string ; content : string ; }; type VersionedDocument = Document & Timestamped & Versioned ;type BaseConfig = { apiUrl : string ; timeout : number ; }; type DevConfig = { debug : boolean ; mockData : boolean ; }; type ProductionConfig = { analytics : boolean ; errorReporting : boolean ; }; type AppConfig = BaseConfig & (DevConfig | ProductionConfig );type AddTimestamp <T> = T & { timestamp : Date };type TimestampedUser = AddTimestamp <Person >;type Override <T, U> = Omit <T, keyof U> & U;type UpdatedPerson = Override <Person , { age : string }>;
错误场景 type Conflict = { prop : string } & { prop : number };type FunctionConflict = ((x : string ) => void ) & ((x : number ) => void );type PrimitiveIntersection = string & number ; type CompatibleIntersection = { a : string } & { b : number }; type OverloadedFunction = { (x : string ): string ; (x : number ): number ; };
10. is 操作符(类型谓词操作符) 功能 创建类型谓词函数,用于类型守卫,帮助 TypeScript 进行类型收窄。
定义实现 function isType (value : unknown ): value is SomeType { return ; }
使用案例 function isString (value : unknown ): value is string { return typeof value === "string" ; } function isNumber (value : unknown ): value is number { return typeof value === "number" ; } function processValue (value : unknown ): string { if (isString (value)) { return value.toUpperCase (); } if (isNumber (value)) { return value.toString (); } return "unknown" ; } interface User { name : string ; age : number ; } function isUser (value : unknown ): value is User { return ( typeof value === "object" && value !== null && "name" in value && "age" in value && typeof (value as any ).name === "string" && typeof (value as any ).age === "number" ); } function isStringArray (value : unknown ): value is string [] { return Array .isArray (value) && value.every (item => typeof item === "string" ); } interface ApiUser { id : number ; name : string ; email : string ; } function isApiUser (data : unknown ): data is ApiUser { return ( typeof data === "object" && data !== null && "id" in data && "name" in data && "email" in data && typeof (data as any ).id === "number" && typeof (data as any ).name === "string" && typeof (data as any ).email === "string" ); } async function fetchUser (id : number ): Promise <ApiUser > { const response = await fetch (`/api/users/${id} ` ); const data = await response.json (); if (isApiUser (data)) { return data; } throw new Error ("Invalid user data" ); } type Animal = | { type : "cat" ; meow : () => void } | { type : "dog" ; bark : () => void }; function isCat (animal : Animal ): animal is { type : "cat" ; meow : () => void } { return animal.type === "cat" ; } function handleAnimal (animal : Animal ) { if (isCat (animal)) { animal.meow (); } else { animal.bark (); } }
错误场景 function badIsString (value : unknown ): value is string { return typeof value === "number" ; } function wrongParameter (value : unknown ): otherValue is string { return typeof value === "string" ; } function badReturnType (value : unknown ):