我想向这个 JS 函数添加 TypeScript 类型:
function getProp(obj, prop) {
if (!obj) {
return undefined;
}
return obj[prop];
}
如果不需要处理未定义
,则可以使用:
function getProp<T, P extends keyof T>(obj: T, prop: P): T[P] {
// ...
}
但是,对于 undefined
,这种使用 | 的幼稚方法未定义
不起作用:
function getProp<T, P extends keyof T>(obj: T | undefined, prop: P): T[P] | undefined {
if (!obj) {
return undefined;
}
return obj[prop];
}
const obj1 = {
id: 1,
name: 'obj1',
};
const obj2 = undefined;
getProp(obj1, 'id');
getProp(obj2, 'id');
^^^ Argument of type '"id"' is not assignable to parameter of type 'never'.ts(2345)
输入此内容的最佳方式是什么?
最佳答案
我想我是否要全力以赴,让 getProp()
函数接受各种 obj
参数,然后允许任何键,如果 obj
可能是未定义
,我会这样做:
function getProp<T,
P extends T extends any ? (undefined extends T ? keyof any : keyof T) : never
>(
obj: T,
prop: P
): T extends any ? (P extends keyof T ? T[P] : undefined) : never;
function getProp<T, P extends keyof T>(obj: T | undefined, prop: P): T[P] | undefined {
if (typeof obj === "undefined") {
return undefined;
}
return obj[prop];
}
这非常复杂,但它有一些可能理想的行为:
const obj1 = {
id: 1,
name: 'obj1',
};
const obj2 = undefined;
const items = [obj1];
getProp(items.find(i => i.id === 1), "id"); // number | undefined
getProp(obj1, "id"); // number
getProp(obj2, "who knows"); // undefined
getProp(Math.random() < 0.5 ? { a: 1 } : { a: "b" }, "a"); // string | number
getProp(Math.random() < 0.5 ? { a: 1 } : { b: 1 }, "z"); // error! "z" not "a" | "b"
getProp(Math.random() < 0.5 ? { a: 1 } : { b: 1 }, "a"); // number | undefined
但是对于您所描述的用例,您只对传入 undefined
感兴趣,因为 obj
可能是 T |对于某些特定的
,并且您永远不会计划实际调用T
,undefinedgetProp(undefined, "something")
。在这种情况下,您的“天真”方法就足够有效:
function getProp<T, P extends keyof T>(obj: T | undefined, prop: P): T[P] | undefined {
if (typeof obj === "undefined") {
return undefined;
}
return obj[prop];
}
观察:
getProp(items.find(i => i.id === 1), "id"); // number | undefined
getProp(obj1, "id"); // number | undefined
getProp(obj2, "who knows"); // error!
getProp(Math.random() < 0.5 ? { a: 1 } : { a: "b" }, "a"); // string | number | undefined
getProp(Math.random() < 0.5 ? { a: 1 } : { b: 1 }, "z"); // error! "z" not "a" | "b"
getProp(Math.random() < 0.5 ? { a: 1 } : { b: 1 }, "a"); // number | undefined
可能唯一“糟糕”的事情是 getProp()
的所有输出在其类型中都包含 undefined
,即使您正在调用 getProp (obj, "id")
,已知定义的 obj
以及已知存在的 "id"
。但这似乎就是你想要的,所以就这样吧。你基本上回答了你自己的问题!
所以,呃,希望有帮助。祝你好运!
关于typescript - 当 T 未定义时如何输入 `K extends keyof T`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58310991/