TypeScript:如何基于同类型中的静态属性值条件定义函数返回类型
实现基于
id的条件返回类型检查 当然可以实现你想要的类型检查效果!核心是把Task改成泛型类型,让id的具体值和run的返回类型建立绑定关系,这样TypeScript就能根据id自动推断并校验run的返回值是否符合对应类型。
修改后的类型定义
我们将Task定义为接受一个泛型参数T(约束为Outputs的键),把id的类型指定为T,同时让run的返回类型对应Outputs[T]:
type Outputs = { "get-name": { name: string; }; "get-age": { age: number; }; "get-favourite-fruits": ("apple" | "strawberry" | "melon")[]; }; // 使用泛型绑定id和run的返回类型 type Task<T extends keyof Outputs = keyof Outputs> = { id: T; run: () => Outputs[T]; };
验证类型检查效果
现在声明task时,TypeScript会根据id的具体值自动推断泛型参数T,并严格校验run的返回值是否匹配Outputs[T]:
const taskOne: Task = { id: "get-name", // ✅ 合法:返回值符合Outputs['get-name'] run: () => { return { name: "frankenstein" }; }, }; const taskTwo: Task = { id: "get-age", // ✅ 合法:返回值符合Outputs['get-age'] run: () => { return { age: 22 }; }, }; const taskThree: Task = { id: "get-favourite-fruits", // ❌ 报错:类型'("apple" | "banana")[]'不可赋值给类型'("apple" | "strawberry" | "melon")[]' run: () => { return ["apple", "banana"]; }, };
更简洁的写法:使用辅助函数
如果你不想每次都手动写: Task,可以创建一个辅助函数来自动推断泛型类型,代码会更简洁且类型更可靠:
function createTask<T extends keyof Outputs>(task: Task<T>): Task<T> { return task; } // 自动推断类型,无需手动指定Task const taskOne = createTask({ id: "get-name", run: () => ({ name: "frankenstein" }), }); const taskThree = createTask({ id: "get-favourite-fruits", // ❌ 同样会触发预期的错误 run: () => ["apple", "banana"], });
为什么原写法无法生效?
原来的Task类型中,id是keyof Outputs(即所有可能的键的联合类型),而run的返回类型是never。由于never是所有类型的子类型,任何返回值都能被赋值给never,导致TypeScript无法进行有效的类型校验。而泛型的方式将id的具体类型和run的返回类型做了一对一的绑定,让TypeScript能精准判断返回值是否合法。
内容的提问来源于stack exchange,提问作者Jake
相关产品推荐
相关产品推荐

