Extreme Explorations of TypeScript's Type System | Learning TypeScript
Generics is that they transform a function based on the type of data you pass into it
function identity <T>(value: T) : T {
return value
}
console.log(identity<Number>(42))
console.log(identity("Hello!"))
console.log(identity<Number>([1, 2, 3]))
Generics for Classes and Interfaces
interface GenericInterface<U> {
value: U
getIdentity: () => U
}
class IdentityClass<T> implements GenericInterface<T> {
value: T
constructor(value: T) {
this.value = value
}
getIdentity () : T {
return this.value
}
}
const myNumberClass = new IdentityClass<Number>(1)
console.log(myNumberClass.getIdentity()) // 1
const myStringClass = new IdentityClass<string>("Hello!")
console.log(myStringClass.getIdentity()) // Hello!
Practical use case: moving beyond primitive types
class Car {
label: string = 'Generic Car'
numWheels: Number = 4
horn() {
return "beep beep!"
}
}
class Truck extends Car {
label = 'Truck'
numWheels = 18
}
class Vespa extends Car {
label = 'Vespa'
numWheels = 2
}
function washCar <T extends Car> (car: T) : T {
console.log(`Received a ${car.label} in the car wash.`)
console.log(`Cleaning all ${car.numWheels} tires.`)
console.log('Beeping horn -', car.horn())
console.log('Returning your car now')
return car
}
const myVespa = new Vespa()
washCar<Vespa>(myVespa)J
const myTruck = new Truck()
washCar<Truck>(myTruck)
export function asApiAction<T extends (...args: any[]) => unknown>(actionCreator: T) {
return actionCreator as (...args: Parameters<typeof actionCreator>) => ApiPromise
}
在这里泛型 T 可以将函数调用处 actionCreator 的参数作为类型变量存下来,如果不写泛型,则 actionCreator 参数 args 的类型无法获得
类型能用推导就用推导获得,除了函数,尽可能手动申明输入和输出的类型
// 多个类型变量之间约束
function pick<T>(o: T, keys: keyof T) {
// xxx
}
pick({a: 1, b: 2}, 'c') // 报错,'c'不属于'a'|'b'
//约束类型变量,通过 bounded polymorphism 为类型变量添加 extends 确定上边界
function longest<T extends { length: number }>(a: T, b: T) {
if (a.length >= b.length) {
return a
} else {
return b
}
}
// 复合过程
type MakePair<T, U> = [T, U]
const make_pair = (x, y) => [x, y]
type Id<T> = T
const id = x => x
// 函数求值和泛型实例化
let pair = make_pair(1, 2)
type StringNumberPair = MakePair<string, number>
// 条件表达式和谓词
let res = x === true ? 'true' : 'false'
type Result = x extends true ? 'true' : 'false'
// 对象解构和 extractType
const { name } = { name: 'xy' }
type NameType<T> = T extends { name: infer N } ? N : never
type res = NameType<{name: 'xy' }>
// 递归类型和递归函数
type List<T> = {
val: T,
next: List<T>
} | null
function length<T>(list: List<T>) {
return list === null ? 0 : 1 + length(list.next)
}
// map && filter && 遍历 & 查找
const res = [1, 2, 3].filter(x => x % 2 === 0).map(x => 2*x)
type A = {
0: 1,
1: 2,
2: '3',
3: '4',
}
type Filter<T extends Record<string, any>, Condition> = {
[K in keyof T]: T[K] extends Condition ? T[K] : never
}[keyof T]
type B = Filter<A, string>