admin管理员组文章数量:1122832
I am working on a project and have a need to do some custom schema work. I have a type of MyModel
and am trying to extract all properties that inherit from SchemaIdentity<any>
and make those properties into a union using ExtractIdentity<>
.
I have ExtractIdentity<MyModel>
, but it is extracting all properties (id
, name
), not the ones that inherit from SchemaIdentity
. The result should be id
What am I doing wrong?
I have tried changing [K in keyof R]: R[K] extends SchemaIdentity<any> ? K : never;
and it seems like narrowing is not working as expected. I would expect any R[K]
that inherits from SchemaIdentity
to return is property name of K
. The name
property on MyModel
has a type of SchemaDefault<string>
yet it's some how matching the type narrowing.
NOTE: I have omitted code in the classes to keep the example smaller.
export abstract class SchemaBase<T extends any> {
}
export class SchemaDefault<T extends any> extends SchemaBase<T> {
}
export class SchemaNumber<T extends number = number> extends SchemaBase<T> {
}
export class SchemaIdentity<T extends string | number> extends SchemaBase<T> {
}
export class SchemaDefinition<T extends {}> extends SchemaBase<T> {
}
export type ExtractIdentity<T> = T extends SchemaDefinition<infer R> ? {
[K in keyof R]: R[K] extends SchemaIdentity<any> ? K : never;
}[keyof R] : never;
type MyModel = SchemaDefinition<{
id: SchemaIdentity<number>;
name: SchemaDefault<string>;
}>
type MyIds = ExtractIdentity<MyModel>
Playground Here
TypeScript Version: 5.6.3
I am working on a project and have a need to do some custom schema work. I have a type of MyModel
and am trying to extract all properties that inherit from SchemaIdentity<any>
and make those properties into a union using ExtractIdentity<>
.
I have ExtractIdentity<MyModel>
, but it is extracting all properties (id
, name
), not the ones that inherit from SchemaIdentity
. The result should be id
What am I doing wrong?
I have tried changing [K in keyof R]: R[K] extends SchemaIdentity<any> ? K : never;
and it seems like narrowing is not working as expected. I would expect any R[K]
that inherits from SchemaIdentity
to return is property name of K
. The name
property on MyModel
has a type of SchemaDefault<string>
yet it's some how matching the type narrowing.
NOTE: I have omitted code in the classes to keep the example smaller.
export abstract class SchemaBase<T extends any> {
}
export class SchemaDefault<T extends any> extends SchemaBase<T> {
}
export class SchemaNumber<T extends number = number> extends SchemaBase<T> {
}
export class SchemaIdentity<T extends string | number> extends SchemaBase<T> {
}
export class SchemaDefinition<T extends {}> extends SchemaBase<T> {
}
export type ExtractIdentity<T> = T extends SchemaDefinition<infer R> ? {
[K in keyof R]: R[K] extends SchemaIdentity<any> ? K : never;
}[keyof R] : never;
type MyModel = SchemaDefinition<{
id: SchemaIdentity<number>;
name: SchemaDefault<string>;
}>
type MyIds = ExtractIdentity<MyModel>
Playground Here
TypeScript Version: 5.6.3
Share Improve this question edited Nov 22, 2024 at 16:25 Agrejus asked Nov 22, 2024 at 16:01 AgrejusAgrejus 7628 silver badges21 bronze badges 4 |1 Answer
Reset to default 2The issue you do have is that all types matches even when you use SchemaNumber
which is slightly diferent but reduce to the same type
If you try this:
type test1 = SchemaNumber<any> extends SchemaIdentity<any> ? true : false
// ^? false
type test2 = SchemaIdentity<any> extends SchemaNumber<any> ? true : false
// ^? true
What you can ses is that SchemaIdentity
extends even SchemaNumber
and further more SchemaDefault
which takes any
as a generic
On that matter try to avoid any
and you can alway avoid them use unknown
instead.
So for it to work you need to have differents types where extends does not match.
If SchemaIdentity
would take a string and only a string then it would work agains SchemaNumber
but still not agains SchemaDefault
.
Another way to make it work is to have different type - in this case have diffent properties / methods etc.
So if you want to keep the generic types simple code your class and it will work - except if all properties match as well.
I hope it helps
本文标签: TypeScriptType Narrowing In Generics Not WorkingStack Overflow
版权声明:本文标题:TypeScript - Type Narrowing In Generics Not Working - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736302477a1931548.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
SchemaDefault
andExtractIdentity
matches look here if that answers your question playground – zedryas Commented Nov 22, 2024 at 16:23class Foo {}; class Bar {}; const foo: Foo = new Bar();
. Also note that this checkR[K] extends SchemaIdentity<any>
will always succeed as the answer by zedryas shows. The word "extends" in this context means "is assignable to", and everything is assignable toany
. – Jared Smith Commented Nov 22, 2024 at 17:10