第 78 期 - TypeScript 5.4's NoInfer Utility Type
摘要
介绍 TypeScript 5.4 中的 NoInfer 实用类型,包括如何使用它控制泛型函数中的类型推断,还通过实例展示了避免类型推断错误的情况。
1. NoInfer 的基本概念
在 TypeScript 5.4 中引入了一个新的实用类型 NoInfer。它可以用来阻止 TypeScript 从泛型函数内部推断类型。例如,有一个泛型函数const returnWhatIPassedIn = <T>(value: T) => value;,当传入"hello"时,TypeScript 会推断出结果result的类型为"hello"。但是如果将value: T改为value: NoInfer<T>,再次传入"hello"时,result就会被推断为unknown,此时需要显式提供类型给returnWhatIPassedIn才能得到期望的返回类型,如const result = returnWhatIPassedIn<"hello">("hello");。
2. 使用场景
2.1 有限状态机示例
- 以创建有限状态机(FSM)的函数为例,函数签名为
declare function createFSM<TState extends string>(config: { initial: TState; states: TState[]; }): TState;。这里有两个地方(initial和states)可能被 TypeScript 用来推断TState类型。 - 当调用这个函数时,如
const example = createFSM({ initial: "not - allowed", states: ["open", "closed"] });,TypeScript 会从initial和states两者推断TState,结果example的类型为"not - allowed" | "open" | "closed",但这可能会有问题。 - 我们希望 TypeScript 只从
states推断TState,不让initial成为推断的候选。这时可以使用 NoInfer,将函数签名改为declare function createFSM<TState extends string>(config: { initial: NoInfer<TState>; states: TState[]; }): TState;,再次调用时,TypeScript 就只会从states推断TState,如果initial的值不在states数组中就会报错。
2.2 切换 NoInfer 的位置
- 如果将 NoInfer 应用到
states上,如declare function createFSM<TState extends string>(config: { initial: TState; states: NoInfer<TState>[]; }): TState;。 - 当调用
createFSM时,只有initial的值才是有效的状态,否则会报错,如createFSM({ initial: "open", states: ["closed"] });会因为"closed"类型与"open"不匹配而报错。
3. 总结
NoInfer 可以用于控制 TypeScript 从泛型函数内部的何处推断类型,在有多个运行时参数引用相同类型参数时非常有用。
