TypeScript约束DummyService返回函数入参key为传入的steps键值
实现带严格类型校验的DummyService
为啥之前的写法不生效
之前给DummyService定了固定的入参类型Definition,这个类型里把steps的key统一定义为宽泛的string类型,相当于提前把实际传入的具体key值(比如"key1"、"key2")的字面量信息给抹平了,TS根本记不住合法key的取值范围,自然不会拦截任意输入的字符串,失去校验能力。
调整方案
核心思路是不给入参写死宽化类型,用泛型把调用时传入的definition结构原原本本捕获下来,再从steps数组中提取所有合法key组成联合类型,绑定到返回的dummyFn入参上。
调整后的核心实现:
// 用泛型捕获传入的steps结构,不做类型宽化 const DummyService = < Steps extends ReadonlyArray<{ key: string, callback?: () => void }> >(definition: { id: string; steps: Steps }) => { // 从传入的steps中提取所有合法的key联合类型 type ValidStepKeys = Steps[number]["key"]; return { dummyFn: (step: { key: ValidStepKeys }) => { console.log(step); } }; };
实际校验效果
- 调用时传入steps包含
{key: "key1"}、{key: "key2"}的definition,返回的dummyFn的key参数会自动被推断为"key1" | "key2"的联合类型,此时传入拼写错误的"key1dsfasd"会直接触发TS类型报错,符合预期。 - 调用时传入steps包含
{key: "key3"}、{key: "key4"}的definition,返回的dummyFn的key参数会自动被推断为"key3" | "key4"的联合类型,此时传入合法的"key3"可以正常通过类型校验。
容易踩的坑
- 不要在调用函数时手动给传入的definition标注原来的宽化
Definition类型,比如const definition: Definition = {...},这种写法会强制把steps的key的字面量类型抹平为通用string,导致泛型捕获失效,校验功能完全失效。 - 直接将对象字面量传给DummyService即可,TS的泛型推断会自动保留key的字面量类型,不会触发不必要的类型宽化,无需额外配置。
内容的提问来源于stack exchange,提问作者Prozy
相关产品推荐
相关产品推荐

