typescript - 在有边界的泛型类型上使用 Partial<T> 的问题
function f<T extends {id: string}>(id: T['id']): Partial<T> {
return {id: id}; // ERROR: Type '{ id: T["id"]; }' is not assignable to type 'Partial<T>'
}
(TypeScript Playground 链接)
我正在尝试弄清楚为什么上面的代码不被允许。它本质上是错误的吗?还是因为 TypeScript 类型系统的限制?
答案#1
这是一个缺失的功能;编译器无法将该赋值视为安全,并且出于与“为什么我不能返回一个泛型 'T' 来满足 Partial
如果你愿意,你可以使用类型断言:
function fAssert<T extends {id: string}>(id: T['id']): Partial<T> {
return {id: id} as Partial<T>; // assert
}
或者你可以分阶段构建返回值(尽管这种方法过于宽松,并允许一些可能不会很快被修复的不可靠的东西):
function fRoundabout<T extends {id: string}>(id: T['id']): Partial<T> {
const ret: Partial<T> = {}; // allowed
ret.id = id; // also works
return ret;
}
我不完全确定你为什么想要将返回类型设为 Partial<T>,因为这种类型在 T 的键上可能有值也可能没有值,而你返回的对象肯定有一个 id 属性,且没有其他属性。在我看来,这更像是 Pick<T, "id"> 而不是 Partial<T>:
function fDifferentReturnType<T extends { id: string }>(id: T['id']): Pick<T, 'id'> {
return { id: id }; // okay
}
由于这个例子只是一个玩具示例,你的实际用例很可能需要 Partial<T> 而不是 {id: T['id']}。但如果不需要,那么你可能会决定完全绕开 Partial 问题。
好的,希望其中一个建议有帮助。祝你好运!
游乐场链接
答案#2
jcalz 提出了 3 个选项。哪一个合适?
我同意他的观点,即从这个“玩具”示例中,并不清楚是否真的需要返回类型 Partial<T>。Pick<T, 'id'> 就足够了。在这种情况下,类型推断工作得很好,而且可能是一个更简单的解决方案:
function f<T extends {id: string}>(id: T['id']) {
return { id }; // type: { id: T['id'] }
}
