我想向此JS函数添加TypeScript类型:
function getProp(obj, prop) {
if (!obj) {
return undefined;
}
return obj[prop];
}
如果不需要处理undefined
,则可以:
function getProp<T, P extends keyof T>(obj: T, prop: P): T[P] {
// ...
}
但是,对于undefined
,这种对| 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)
最好的输入方式是什么?
答案 0 :(得分:2)
如果要全力以赴,使getProp()
函数接受各种obj
参数,然后允许obj
为{{1 }},我会做这样的事情:
undefined
这非常复杂,但它可能具有一些令人希望的行为:
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
的{{1}},而且您从不打算实际致电obj
。在这种情况下,您的“幼稚”方法效果很好:
T | undefined
观察:
T
唯一可能的“坏处”是,getProp(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
(已知定义的{{ 1}}和已知的getProp()
。但这似乎就是您想要的,所以就去了。您基本上回答了自己的问题!
所以,希望能有所帮助。祝你好运!
答案 1 :(得分:2)
我认为这是您想要实现的目标:
function getProp<O, P extends O extends undefined ? any : keyof O>(obj: O, prop: P) {
if (!obj) {
return undefined;
}
return obj[prop];
}
const obj1 = {
id: 1,
name: 'obj1',
};
const obj2 = undefined;
getProp(obj1, 'id');
getProp(obj2, 'id');
因此,如果未定义第一个参数,则将第二个类型设置为any
。我不键入return,因为可以很好地推断出它。 Playground