【问题标题】:How to switch on the property of generic object in typescript?如何在打字稿中打开泛型对象的属性?
【发布时间】:2021-05-14 22:49:09
【问题描述】:

我有一个属性类型是泛型的类型。

我想打开属性来推断泛型值的类型。

这是我为实现这一目标所做的代码。我认为这会起作用,因为编译器应该具有推断类型所需的所有信息。显然不是,因为编译器会抛出错误。

type Foo<T> = {
    value: T
}

type A = { type: 'a', data: number }
type B = { type: 'b', data: string }
type AB = A | B

function doStuff(foo: Foo<AB>) {
    switch(foo.value.type) {
        case 'a': {
            // here TS knows that foo.value is an `A`, why isnt foo a Foo<A> ?
            return doStuffA(foo) // Error (1) on foo
        }
        case 'b': {
            return doStuffB(foo) // Error(2) also on foo
        }
    }
}

function doStuffA(foo: Foo<A>) {
    // ...
}

function doStuffB(foo: Foo<B>) {
    // ...
}

还有错误:

(Error 1)
Argument of type 'Foo<AB>' is not assignable to parameter of type 'Foo<A>'.
  Type 'AB' is not assignable to type 'A'.
    Type 'B' is not assignable to type 'A'.
      Types of property 'type' are incompatible.
        Type '"b"' is not assignable to type '"a"'.

(Error 2)
Argument of type 'Foo<AB>' is not assignable to parameter of type 'Foo<B>'.
  Type 'AB' is not assignable to type 'B'.
    Type 'A' is not assignable to type 'B'.
      Types of property 'type' are incompatible.
        Type '"a"' is not assignable to type '"b"'.

这是对 Typescript 的限制吗?还是我做错了什么?

【问题讨论】:

标签: typescript typescript-generics


【解决方案1】:

感谢 cmets 的 Ben Wainwright,我找到了解决方案。

我需要创建细化Foo&lt;T&gt; 类型的函数。

type Foo<T> = {
    value: T
}

type A = { type: 'a', data: number }
type B = { type: 'b', data: string }
type AB = A | B

// here, isA tells the TS compiler that foo is indeed a Foo<A>
function isA(foo: Foo<AB>): foo is Foo<A> {
    return foo.value.type === 'a'
}

// same here for Foo<B>
function isB(foo: Foo<AB>): foo is Foo<B> {
    return foo.value.type === 'b'
}

function doStuff(foo: Foo<AB>) {
    if(isA(foo)) {
        // it works ! here TS recognise foo as Foo<A>
        return doStuffA(foo)
    } else if(isB(foo)) {
        // same here, TS knows that foo is a Foo<B>
        return doStuffB(foo)
    }
}

function doStuffA(foo: Foo<A>) {
    // ...
}

function doStuffB(foo: Foo<B>) {
    // ...
}

【讨论】:

    猜你喜欢
    • 2021-12-06
    • 2019-03-12
    • 2020-10-11
    • 2021-12-30
    • 2021-09-29
    • 2021-12-16
    • 2019-01-16
    • 2020-01-08
    • 1970-01-01
    相关资源
    最近更新 更多