[英]TypeScript Generics problem: type T (extends Type) is not assignable to T
I have a problem with TypeScript generics in Deno.我对 Deno 中的 TypeScript generics 有疑问。
abstract class Packet {
public abstract read(): Uint8Array;
public abstract write(data: Uint8Array): void;
}
type PacketData = Packet | Uint8Array;
type HookCallbackResult<T extends PacketData> = T | null | undefined;
type HookCallback<T extends PacketData> = (data: T) => HookCallbackResult<T>;
interface HookCallbackInfo<T extends PacketData> {
packetType: typeof Packet | "any";
callback: HookCallback<T>;
}
let callbacks: HookCallbackInfo<PacketData>[] = [];
function hook<T extends PacketData>(packetType: typeof Packet | "any", callback: HookCallback<T>) {
callbacks.push({ packetType, callback });
// ^^^^^^^^
// error: TS2322 [ERROR]: Type 'HookCallback<T>' is not assignable to type 'HookCallback<PacketData>'.
// Types of parameters 'data' and 'data' are incompatible.
// Type 'PacketData' is not assignable to type 'T'.
// 'PacketData' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'PacketData'.
// Type 'Packet' is not assignable to type 'T'.
// 'Packet' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'PacketData'.
}
My purpose is to force a callback which is passed as 2nd argument to hook
function to return a result of the same type as its argument OR null
OR undefined
and this type should be Uint8Array
or already parsed Packet
(or its child class) and nothing else.我的目的是强制回调作为第二个参数传递给
hook
function 以返回与其参数或null
或undefined
相同类型的结果,并且此类型应为Uint8Array
或已解析的Packet
(或其子类),仅此而已. And hook
function should store this hook callback for further use.并且
hook
function 应该存储这个钩子回调以供进一步使用。 Deno's version of TypeScript compiler panics on adding a callback to an object (declared with interface HookCallbackInfo
) array. Deno 的 TypeScript 编译器版本在向 object(使用接口
HookCallbackInfo
声明)数组添加回调时出现恐慌。
I guess I made a mistake somewhere with generics cause I don't understand properly how they work in TypeScript with these multiple type definitions (like Type1 | Type2 | Type3
).我想我在 generics 的某个地方犯了一个错误,因为我不明白它们如何在 TypeScript 中使用这些多种类型定义(如
Type1 | Type2 | Type3
)。 Could you pls explain me what exactly I did wrong and how to do what I want in the proper way?你能解释一下我到底做错了什么以及如何以正确的方式做我想做的事吗?
Your callbacks
array is an array of HookCallbackInfo<PacketData>
values, which means their callback
fields must contain functions of type (data: PacketData) => HookCallbackResult<PacketData>
.您的
callbacks
数组是HookCallbackInfo<PacketData>
值的数组,这意味着它们的callback
字段必须包含(data: PacketData) => HookCallbackResult<PacketData>
类型的函数。 In your hook
function, you're passing in callbacks of some unknown type T
that extends PacketData
, so the callback you're trying to provide is a function of type (data: T) => HookCallbackResult<T>
.在你的
hook
function 中,你传入了一些未知类型T
的回调,它扩展PacketData
,所以你试图提供的回调是一个 function 类型(data: T) => HookCallbackResult<T>
。
This is where the problem lies: callbacks
needs functions that can be called on any PacketData value, whereas you're trying to provide it with callbacks that can only be called on some PacketData values.这就是问题所在:
callbacks
需要可以在任何PacketData 值上调用的函数,而您试图为它提供只能在某些PacketData 值上调用的回调。 The type system detects and prevents you from doing so.类型系统会检测并阻止您这样做。
To see why this matters, consider what could go wrong if the type system didn't check this:要了解为什么这很重要,请考虑如果类型系统没有检查,go 会出现什么错误:
const myFn: (v: Packet) => null = ...
hook<Packet>("any", myFn);
const array: Uint8Array = ...
callbacks[0](array); // we've called myFn with the wrong argument type!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.