简体   繁体   English

从泛型类型推断返回类型

[英]Infer return type from generic types

I want to infer a type in a specific situation to either get a Box<T> or a T , based on an input parameter, but I end up with Box<unknown> and unknown instead.我想根据输入参数推断特定情况下的类型以获取Box<T>T ,但我最终得到Box<unknown>和 unknown 。 I think it is because of my usage of W extends Wrap<T> , but I don't know how to express this better.我认为这是因为我使用了W extends Wrap<T> ,但我不知道如何更好地表达这一点。

See this code example, hover over boxResult and noBoxResult to see the inferred types are not ideal for me:请参阅此代码示例,hover over boxResultnoBoxResult以查看推断的类型对我来说并不理想:

// Type definitions

interface ComplicatedDataContainer<T> {
    // contains many Ts in some complicated fashion
}
interface WrapA<T> {
    v: ComplicatedDataContainer<T>,
    p: "Box"
}
interface WrapB<T> {
    v: ComplicatedDataContainer<T>,
    p: "NoBox"
}
type Wrap<T> = WrapA<T> | WrapB<T>;

type Box<T> = {
    t: T
}

type SelectThing = <T, W extends Wrap<T>>(id: string, w: W) => W extends {p: "Box"} ? Box<T> : T

// Usage example

const wBox: WrapA<string> = {
    v: "",
    p: "Box"
}

const wNoBox: WrapB<string> = {
    v: "",
    p: "NoBox"
}

const selector: SelectThing = (id: string, w: Wrap<any>) => {throw new Error()}; // dont care about runtime behavior here, real impls are way more complicated

// I want the type of this to be Box<string>, but it is Box<unknown>
const boxResult = selector("", wBox);
// I want the type of this to be string, but it is unknown
const noBoxResult = selector("", wNoBox);

You can run this example here .您可以在此处运行此示例。

The problem is that there's no inference site for T so it defaults to unknown .问题是T没有推理站点,因此它默认为unknown Actually you don't need a separate type parameter T here, since it can be derived from the type parameter W .实际上,这里不需要单独的类型参数T ,因为它可以从类型参数W派生。 The Unwrap type below does this derivation.下面的Unwrap类型执行此推导。

type Unwrap<W extends Wrap<any>> = W extends Wrap<infer T> ? T : never

type SelectThing =
    <W extends Wrap<any>>(id: string, w: W) => W extends {p: "Box"} ? Box<Unwrap<W>> : Unwrap<W>

Playground Link 游乐场链接

Note that I had to fill in ComplicatedDataContainer in the example so that it depends on T in some way, to avoid unintended structural equivalence .请注意,我必须在示例中填写ComplicatedDataContainer ,以便它以某种方式依赖于T ,以避免意外的结构等价

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM