函数类型也属于对象类型
type Add = (a: number, b: number) => number
type IsFunctionEqualObject = Add extends Record<string, any> ? 1 : 2
// type IsFunctionEqualObject = 1
注意点:
变量需要定义在<>
内部,参考00007-easy-readonly
/** 这里定义了K变量,并且给了默认值,使用时不需要传 */
type MyReadonly<T, K = keyof T> = {
readonly [K in keyof T]: T[K]
}
参考00012-medium-chainable-options.ts
When conditional types act on a generic type, they become distributive when given a union type(the union type should be on the left of extends key)
type ToArray<Type> = Type extends any ? Type[] : never
type StrArrOrNumArr = ToArray<string | number>
// Output: type StrArrOrNumArr = string[] | number[]
TypeScript 没有内置Tuple
类型,但是可以自定义为type Tuple = readonly unknown[]
使用in
遍历Tuple
的值,作为 object 的 key,参考00011-easy-tuple-to-object.ts
type TupleToObject<T extends readonly any[]> = {
[K in T[number]]: K
}
获取Tuple
的长度, 00018-easy-tuple-length.ts
type Length<T extends readonly any[]> = T['length']
type Concat<T extends readonly any[], U extends readonly any[]> = [...T, ...U]
用keyof
遍历数组, 参考00020-medium-promise-all
递归遍历数组,并返回数组类型,参考00459-medium-flatten
type A = ['1', '2']
type ArrayToUnion<T extends any[]> = T[number]
type B = ArrayToUnion<A>
// type B = '1' | '2'
type Space = ' ' | '\n' | '\t'
type Trim<S extends string> = S extends
| `${Space}${infer R}`
| `${infer R}${Space}`
? Trim<R>
: S
type MyCapitalize<S extends string> = S extends `${infer F}${infer R}`
? `${Uppercase<F>}${R}`
: S
type B = '' extends `${infer Head}${infer Tail}` ? 1 : 2
// type B = 2
type NumberToString<T extends number> = `${T}`
type A1 = NumberToString<1.1>;
// type A1 = "1.1"
type A2 = NumberToString<1.0>
// type A2 = "1"
type IsNever<T> = [T] extends [never] ? true : false
/** 这种情况下 A也是never */
type E = []
type A = IsNever<`__${E[number]}`>
// type A = true
操作 "对象类型" 生成key
的联合类型,Link
type Arrayish = { [n: number]: unknown }
type A = keyof Arrayish // number
type Mapish = { [k: string]: boolean }
type M = keyof Mapish // number | string
interface Todo {
title: string
description: string
completed: boolean
}
type TodoKeys = keyof Todo // 'title' | 'description' | 'completed'
type name = 'firstname' | 'lastname'
type TName = {
[key in name]: string
}
// TName = { firstname: string, lastname: string }
当 U 为对象时候,会在 Mapping Type 外部分布,当 U 为类似 string 或者 number 时候,会在 Mapping Type 内部分布),就能触发 Distributive Conditional Types
type A = {
name: string
}
type B = {
age: number
}
type Dis<T> = {
[K in keyof T]: K
}
type res1 = Dis<A> | Dis<B>
type res2 = Dis<A | B>
type result = Equal<res1, res2>
需跟在extends
关键字后面
用于函数参数的例子
type MyParameters<T extends (...args: any[]) => any> = T extends (
...args: infer R
) => any
? R
: []
用于数组的例子
type Push<T extends any[], U> = [...T, U]
用于字符串的例子
type TrimLeft<S extends string> = S extends `${Space}${infer R}`
? TrimLeft<R>
: S
// src/02852-medium-omitbytype.ts
type OmitByType<T, U> = NonNullable<{
[K in keyof T as T[K] extends U ? never : K]: T[K]
}>
type ExtractToObject1<T extends Record<string, unknown>, U extends keyof T> = {
// 左边的K会被`as`关键字改写 但是右边的K不会(始终为keyof T)
[K in keyof T as K extends U ? keyof T[U] : K]: K
}
type test2 = {
id: '1'
prop1: { zoo: '2' }
prop2: { foo: '4' }
}
type A = ExtractToObject1<test2, 'prop1'>
/* Output:
type A = {
id: 'id',
zoo: 'prop1',
prop2: 'prop2'
}
*/
type MyAwaited<T extends PromiseLike<any>> = T extends PromiseLike<infer R>
? R extends PromiseLike<any>
? MyAwaited<R>
: R
: T
在 typescript 中,无法使用+
, -
, *
, /
等运算符,但是可以通过控制数组的长度来计算
type PlusOne<T extends any[]> = [0, ...T]['length']
type MinusOne<T extends any[]> = T extends [0, ...infer R] ? R['length'] : never
type MultiplyByTwo<T extends any[]> = [...T, ...T]['length']
type PlusOneResult = PlusOne<[1, 1, 1]>
// type PlusOneResult = 4
type MinusOneResult = MinusOne<[1, 1, 1]>
// type MinusOneResult = 2
type MultiplyByTwoResult = MultiplyByTwo<[1, 1, 1]>
// type MultiplyByTwoResult = 6
内置工具函数 Utility Types
用法:Exclude<UnionType, ExcludedMembers>
用于排除联合类型里的部分成员
type T1 = Exclude<'a' | 'b' | 'c', 'a' | 'b'>
// type T1 = "c"
type T2 = Exclude<string | number | (() => void), Function>
// type T2 = string | number
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'square'; x: number }
| { kind: 'triangle'; x: number; y: number }
type T3 = Exclude<Shape, { kind: 'circle' }>
type T3Result =
| {
kind: 'square'
x: number
}
| {
kind: 'triangle'
x: number
y: number
}