Extreme Explorations of TypeScript's Type System | Learning TypeScript

Generic

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 Constructor

// 复合过程
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>