[英]Typescript not understanding that T extends interface in a specific complex custom type
So I'm using the Paths
type I got from here , full disclosure, I don't fully understand how it's built and it will probably assist me in understanding the problem, I'll have my implementation of it at the bottom.所以我使用的是我从这里得到的
Paths
类型,完全公开,我不完全理解它是如何构建的,它可能会帮助我理解问题,我将在底部实现它。 In summary if I have the interface:总之,如果我有接口:
interface Person {
name: string,
contacts: {
email: string,
phone: string,
}
}
Then Paths<Person>
would result in union of literal types:然后
Paths<Person>
将导致文字类型的联合:
'name' | 'contacts' | 'contacts.email' | 'contacts.phone'
But when trying to use it with a generic that extends some type, I'm running into weird troubles.但是当尝试将它与扩展某种类型的泛型一起使用时,我遇到了奇怪的麻烦。
function foo<T extends Person> {
let personParamGood: Paths<Person>;
personParamGood = 'name' // great, works.
let personParamBad: Paths<T>
personParamBad = 'name' // typescript screams at me
}
The type error I get says我得到的类型错误说
error TS2322: Type '"name"' is not assignable to type 'T extends object ? { [K in keyof T]-?: K extends string | number ? `${K}` | Join<K, T[K] extends object ? { [K in keyof T[K]]-?: K extends string | number ? `${K}` | Join<K, never> : never; }[keyof T[K]] : ""> : never; }[keyof T] : ""'.
I don't get why, shouldn't T
basically be Person
?我不明白为什么,
T
基本上不应该是Person
?
It does work on a simple type:它确实适用于简单的类型:
function foo<T extends Person> {
let personParamGood: keyof Person;
personParamGood = 'name' // great, works.
let personParamGoodToo: keyof T
personParamGoodToo = 'name' // great, works.
}
My implementation of Paths
:我的
Paths
实现:
type Prev = [never, 0, 1, 2, 3, 5, 6, 7, 8, ...0[]];
type Join<K, P> = K extends string | number
? P extends string | number
? `${K}${'' extends P ? '' : '.'}${P}`
: never
: never;
export type Paths<T, D extends number = 10> = [D] extends [never]
? never
: T extends object
? {
[K in keyof T]-?: K extends string | number
? `${K}` | Join<K, Paths<T[K], Prev[D]>>
: never;
}[keyof T]
: '';
That's because T
will never resolve inside the function implementation as it can be anything.这是因为
T
永远不会在function 实现中解析,因为它可以是任何东西。 You added an extends Person
constraint on it but it can still be anything that extends Person
.您在其上添加了
extends Person
约束,但它仍然可以是扩展Person
的任何内容。 The actual T
type is only known outside the function.实际的
T
型仅在 function 之外已知。
Notice how this code works when you hover the person
variable:请注意当您 hover
person
变量时此代码如何工作:
interface Person {
name: string,
contacts: {
email: string,
phone: string,
}
}
interface ExtendedPerson extends Person {
address: string;
}
declare function foo<T extends Person>(): Paths<T>;
const person = foo<ExtendedPerson>();
But you'll never be able to make T
(and thus Paths<T>
) resolve to an actual type inside the function implementation, that's how generics work in TypeScript and any other language.但是您将永远无法使
T
(因此Paths<T>
)解析为 function 实现中的实际类型,这就是 generics 在 Z558B544CF685F39D34E4903E3 中的工作方式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.