【问题标题】:Infering generic types in typescript在打字稿中推断泛型类型
【发布时间】:2022-01-11 13:41:52
【问题描述】:

我试图在 Typescript 中推断泛型,但我似乎无法控制我做错了什么。我的具体例子会比较大,留在这里,但我做了一个小的打字稿游乐场链接,它完全说明了我面临的问题。

这是link

基本上,我试图从类层次结构中推断出一个通用参数:

type payloadType = {
    [key:string]: string
}

type specificPayloadB = {
    a: string
}

type specificPayloadC = {
    a: string,
    b: string
}

class A<TPayload extends payloadType = any> {}
class B<TPayload extends specificPayloadB = specificPayloadB> extends A<TPayload> {}
class C extends B<specificPayloadC> {}

type InferKeys<TType> = TType extends A<infer Keys> ? Keys : never;
class extender<
   TType extends A,
   TKeys = InferKeys<TType>
> {}

function getClass<TClass extends A>(): extender<TClass> {
    return new extender<TClass>();
}

let testExtenderB = getClass<B>();
let testExtenderC = getClass<C>();

上面的例子没有给出编译错误,但是当用 typescript 检查返回的变量类型时,testExtenderB 被识别为 extender&lt;B&lt;specificPayloadB&gt;, payloadType&gt; 这是正确的,但根据提供的信息,它可以更正确地识别为extender&lt;B&lt;specificPayloadB&gt;, specificPayloadB&gt;

我认为testExtenderC 变量也是如此,它被标识为extender&lt;C, payloadType&gt;,而不是被标识为extender&lt;C, specificPayloadC&gt;

我在这里做错了吗?是否可以在不向 typescript 显式提供类型的情况下实现变量的正确识别?

【问题讨论】:

    标签: typescript type-inference


    【解决方案1】:

    Typescript 有一个结构化的类型系统。对于对象类型,这意味着类型的成员在确定类型兼容性时很重要(请参阅FAQ)。这意味着未使用的类型参数在类型系统中不是很重要。由于您没有在 A 中使用 TPayload,因此 type 参数在类型系统中没有任何意义,因此在推理过程中,在某些情况下它会以默认值结束。

    如果您添加一个成员,推理将按您的预期工作:

    class A<TPayload extends payloadType = any> { p!: TPayload }
    

    Playground Link

    【讨论】:

    • 这是否意味着我需要在某个地方实际定义该变量,或者只是简单地添加它,如果我从不打算将它用于其他任何事情,则让它未定义?我对! 感叹号表示法不熟悉,你能解释一下它的作用吗?
    • 你可以不定义它只需要是类的成员。 ! 告诉编译器不要抱怨在初始化或构造函数中没有分配值
    猜你喜欢
    • 1970-01-01
    • 2022-11-23
    • 2020-12-17
    • 1970-01-01
    • 2021-03-10
    • 1970-01-01
    • 2021-05-06
    • 2020-03-22
    • 2021-09-29
    相关资源
    最近更新 更多