Выведите тип переменной в универсальном интерфейсе

#angular #typescript #typescript-generics

Вопрос:

У меня есть следующий пример.

 enum Foo {
    bar,
    baz
}

interface IBar {
    qux: number
}

interface IBaz {
    quux: string
}

type InterfaceType<T> = 
    T extends Foo.bar ? IBar :
    T extends Foo.baz ? IBaz : never;
    
interface ICorge<T> {
    foo: T
    attributes: InterfaceType<T>
}

const grault: Array<ICorge<unknown>> = [
    {
        foo: Foo.bar,
        attributes: {
            qux: 404
        }
    }, {
        foo: Foo.baz,
        attributes: {
            quux: "not found"
        }
    }   
]
 

Я хочу, чтобы тип моего интерфейса ICorge автоматически определялся по типу foo . Есть ли способ сделать это правильно в машинописном тексте?

Ответ №1:

Настоящая церемония с типами. Немного более практичное решение типа:

 interface IBar {
    foo: 'bar'
    attributes: {
      qux: number
    }
}

interface IBaz {
    foo: 'baz'
    attributes: {
      quux: string
    }
}

const grault: (IBar | IBaz)[] = [
    {
        foo: 'bar',
        attributes: {
            qux: 44
        }
    }, {
        foo: 'baz',
        attributes: {
            quux: "not found"
        }
    }   
]
 

Игровая площадка TS

По крайней мере, я бы настоятельно не советовал enums использовать производственный код без крайней необходимости.

Комментарии:

1. Это всего лишь простой пример из гораздо более сложной проблемы, и использование вашего решения добавило бы много повторений. Но из любопытства, почему бы вам не посоветовать против enums ?

2. Они создают много дополнительного кода и могут значительно снизить производительность при чрезмерном использовании. Я бы предположил const enum , что это хороший компромисс, если хотите enums .

3. В любом случае. InterfaceType выглядит очень тяжелым. Вы можете достичь того же результата с помощью простого типа сопоставления: tsplay.dev/mbkRbW . или с перечислениями: tsplay.dev/mA7EXw

Ответ №2:

Правка: Извините, я | сделал что-то не так.

Просто сделай:

 const grault: Array<ICorge<Foo.bar> | ICorge<Foo.baz>> = [
    {
        foo: Foo.bar,
        attributes: {
            qux: 404
        }
    }, {
        foo: Foo.baz,
        attributes: {
            quux: "not found"
        }
    }   
]
 

Посмотрите на детскую площадку TS

Комментарии:

1. Это так просто, чем больше я открываю для себя универсальные шрифты, тем больше они мне нравятся. Спасибо.