| 3 type C = 1 | 2 | 3 | ... // write all number // C = number type D = '' | 'a' | 'b' | ... // write all string // D = string type E = true | false // E = boolean Type 就像是集合 (Set) TS
做任何運算 | > 可以做 Type Level Programming | > 定義⾃然數 | > 可以做到⼀些 Dependent type 的效果 | > Type check is undecidable | > Implement Collatz | > The Undecidability of the Generalized Collatz Problem
Square = { kind: 'square' side: number } type Shape = Circle | Square Tagged Union Type |> Sum type |> 必須加上識別屬性 |> 需要透過屬性判定, 來完成 type guard |> 沒有 Pattern Match TS function f(s: Shape) { if (s.kind === 'circle') { return s.radius } if (s.kind === 'square') { return s.side } }
type Square = { kind: 'square', side: number } type Shape = Circle | Square function f(s: Shape) { if (s.kind === 'circle') { return s.radius } if (s.kind === 'square') { return s.side } } data Shape = Circle { radius :: Float } | Square { side :: Float } f :: Shape -> Float f Circle { radius } = radius f Square { side } = side
type Square = { kind: 'square', side: number } type Shape = Circle | Square function f(s: Shape) { if (s.kind === 'circle') { return s.radius } if (s.kind === 'square') { return s.side } } type Shape = | Circle of radius: float | Square of side: float let f shape = match shape with | Circle(radius = r) -> r | Square(side = s) -> s
T; // Remove types from T that are assignable to U type Filter<T, U> = T extends U ? T : never; // Remove types from T that are not assignable to U type Result1 = Diff<'1' | '2' | '3', '3'> // '1' | '2' type Result2 = Filter<'1' | '2' | '3', '3'> // '3' type UnionToIntersection<U> = ( U extends never ? never : (arg: U) => never ) extends (arg: infer I) => void ? I : never; type UnionToTuple<T> = UnionToIntersection< T extends never ? never : (t: T) => T > extends (_: never) => infer W ? [ ... UnionToTuple<Exclude<T, W >> , W] : []; type A = UnionToTuple<'1' | '2' | '3'> // ['1', '2', '3'] Syntax 混亂 |> 容易把 Type 跟 Code 混在⼀起 |> Type syntax 可讀 性極差 TS
= (p: primitiveType) => { if (p === 'string') { p // type is 'string' } } const b = <T extends primitiveType>(p: T) => { if (p === 'string') { p // type is still primitiveType } } Union type 的 type guard 在泛型中無 效 TS #36772
沒有真正的 Tagged Union Type |> 沒有 Pattern Match |> 沒有 New Type |> 難以理解的 Type Error Message |> 缺陷 |> Unsoundness |> Syntax 混亂 |> Type Infer 很差 |> Error 不是 First Class
盡可能保持 Function 是 Pure |> 盡可能使⽤ immutable 的⽅式操 作資料 |> 留意任何 mutable 的 操作 |> 可以考慮採⽤ eslint-plugin- immutable type A = { name: string, account: number } let a: A = { name: 'jerry', account: 123456 } type B = { name: string, account: number | string } let b: B = a b.account = '123' a.account.toFixed(0) // Runtime error