如何在TypeScript函数中根据children参数限制initial参数类型?
用TypeScript限制initial参数必须是children数组中的元素
先看我原本的代码:
interface INavigation { children: string[]; initial: string; } function navigation({ children, initial }: INavigation) { return null }
我希望把initial参数的输入限制为children数组里的元素,比如:
// 合法调用 navigation({ children: ["one", "two", "three"], initial: "one" }) navigation({ children: ["one", "two", "three"], initial: "two" }) // 应该抛出类型错误:Type 'four' is not assignable to type 'one' | 'two' | 'three'. navigation({ children: ["one", "two", "three"], initial: "four" })
目前我只能想到在函数内部做运行时校验的方案:
function navigation({ children, initial }: INavigation) { if (!children.includes(initial)) { throw new Error(`${initial} is invalid. Must be one of ${children.join(',')}.`) } return null }
解决方案:用TypeScript泛型实现编译时约束
完全可以通过TypeScript的泛型在编译阶段就完成这个限制,同时也可以保留运行时校验兼容非TS场景。
直接实现泛型函数
function navigation<T extends string>({ children, initial }: { children: T[], initial: T }) { // 可选:保留运行时检查,防止非TypeScript调用传入非法值 if (!children.includes(initial)) { throw new Error(`${initial} is invalid. Must be one of ${children.join(',')}.`) } return null }
复用泛型接口的写法
如果需要复用这个类型定义,可以改成泛型接口:
interface INavigation<T extends string> { children: T[]; initial: T; } function navigation<T extends string>(props: INavigation<T>) { if (!props.children.includes(props.initial)) { throw new Error(`${props.initial} is invalid. Must be one of ${props.children.join(',')}.`) } return null }
这样调用时,TypeScript会自动根据children的字面量数组推断出T的联合类型(比如"one" | "two" | "three"),initial只能传入这个范围内的值,非法值会直接在编译阶段报错,不需要等到运行时。
内容的提问来源于stack exchange,提问作者davidhu
相关产品推荐
相关产品推荐

