推断超级类型的通用包装纸元组
我正在尝试在打字稿中创建一种类型约束,该约束可以为包装类型强制实施Supertype关系。 假设我定义了以下类型(以及用于构建它的实用程序函数):
interface Wrapper<T> {
item: T;
}
function wrap<T>(t: T): Wrapper<T> {
return { item: t }
}
然后,我创建了以下类型来推断超级类型的关系(我在0
vs 下方解释了Never
问题):
type SuperTypesWrappers<C, T extends ReadonlyArray<Wrapper<any>>> = {
[K in keyof T]: T[K] extends Wrapper<infer V> ?
C extends V ? Wrapper<V> :
0 : 0 // never : never -> doesn't work
};
我定义了3个示例包装器,如以下内容:
interface A { a: string; }
const A = wrap<A>({ a: 'a' });
interface B { b: string; }
const B = wrap<B>({ b: 'b' });
interface C extends B { c: string; }
const C = wrap<C>({ b: 'b', c: 'c' });
以及一种验证约束的类型:
// WORKS FINE: type Test1 = [0, Wrapper<B>]
type Test1 = SuperTypesWrappers<C, [typeof A, typeof B]>;
如预期,类型数组中的第一个项目是0
,因为a
不是c
的超级模型,而是b
是。
到目前为止,一切都很好。
然后,我创建了一个AUX类型来实施整体数组有效性:它返回数组类型,因为它是或从不代码>包装器&lt; x&gt;
:
type ValidSuperTypesWrappers<X> = X extends ReadonlyArray<Wrapper<any>> ? X : never;
// WORKS FINE: never
type Test2 = ValidSuperTypesWrappers<Test1>;
然后,我创建了一个利用这两种类型的函数:
export function defineHierarchy<C, T extends ReadonlyArray<Wrapper<any>>>(
wrapper: Wrapper<C>,
superWrappers: ValidSuperTypesWrappers<SuperTypesWrappers<C, T>>
): ValidSuperTypesWrappers<SuperTypesWrappers<C, T>> {
// some implementation
return superWrappers;
}
当我调用它时,我希望检查第二个参数,在下面的示例中,它应该引起类型错误(基于示例类型test1
和test2
)的情况:
// DOES NOT WORK: should raise type error for the array argument!
// inferred type: const h: readonly Wrapper<any>[]
const h = defineHierarchy(C, [A, B]);
可能我缺少某些东西,还是可能是一个错误?如何更改这些类型以使其在上面的defineHierArchy
函数中起作用(可能不指定函数调用中的通用类型参数)?
注1:如果我使用从不:
在supertypeswrappers
中,甚至test2
不起作用:
// DOES NOT WORK: type Test2 = [never, Wrapper<B>]
type Test2 = ValidSuperTypesWrappers<Test1>;
注2:我不想依靠partial&lt; t&gt;
来表达supertype约束,上面的类型应更好地表示约束。
I'm trying to create a type constraint in TypeScript that enforces supertype relationship for a wrapped type.
Let's suppose I defined the following type (and a utility function to build it):
interface Wrapper<T> {
item: T;
}
function wrap<T>(t: T): Wrapper<T> {
return { item: t }
}
Then I've created the following type to infer the super type relationship (I'm explaining below the 0
vs never
issue):
type SuperTypesWrappers<C, T extends ReadonlyArray<Wrapper<any>>> = {
[K in keyof T]: T[K] extends Wrapper<infer V> ?
C extends V ? Wrapper<V> :
0 : 0 // never : never -> doesn't work
};
I defined 3 example wrappers, like the following:
interface A { a: string; }
const A = wrap<A>({ a: 'a' });
interface B { b: string; }
const B = wrap<B>({ b: 'b' });
interface C extends B { c: string; }
const C = wrap<C>({ b: 'b', c: 'c' });
And a type to verify the constraint:
// WORKS FINE: type Test1 = [0, Wrapper<B>]
type Test1 = SuperTypesWrappers<C, [typeof A, typeof B]>;
As expected, the first item in the type array is 0
because A
is not supertype for C
, but B
is.
So far, so good.
Then I created an aux type to enforce the array validity as a whole: it returns the array type as it is, or never
, if it has some items that are not Wrapper<X>
:
type ValidSuperTypesWrappers<X> = X extends ReadonlyArray<Wrapper<any>> ? X : never;
// WORKS FINE: never
type Test2 = ValidSuperTypesWrappers<Test1>;
Then I created a function that leverages both types:
export function defineHierarchy<C, T extends ReadonlyArray<Wrapper<any>>>(
wrapper: Wrapper<C>,
superWrappers: ValidSuperTypesWrappers<SuperTypesWrappers<C, T>>
): ValidSuperTypesWrappers<SuperTypesWrappers<C, T>> {
// some implementation
return superWrappers;
}
And when I invoke it, I'm expecting the second parameter to be checked, and in the following example it should raise a type error (based on what happens in the example types Test1
and Test2
):
// DOES NOT WORK: should raise type error for the array argument!
// inferred type: const h: readonly Wrapper<any>[]
const h = defineHierarchy(C, [A, B]);
Probably I'm missing something, or could it be a bug? How can I change these types to make it work in the defineHierarchy
function above (possibly without specifying the generic type arguments in the function call)?
NOTE 1: If I use never : never
in SuperTypesWrappers
, even Test2
doesn't work:
// DOES NOT WORK: type Test2 = [never, Wrapper<B>]
type Test2 = ValidSuperTypesWrappers<Test1>;
NOTE 2: I would not like to rely on Partial<T>
to express a supertype constraint, the type above should represent the constraint better.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论