Машинопись: проблема с generi c Parameter / ReturnType и String Enums - PullRequest
0 голосов
/ 07 мая 2020

В настоящее время я пытаюсь добавить правильную типизацию к следующей упрощенной функции:

getProperty(property:string):any

Моя цель - сделать возможным передать параметр свойства как string или string enum и получить правильный результат введите его.

Для этого я создал новый string enum Свойство:

enum Property {
    ENABLED = 'enabled',
    SIZE    = 'size'
}

a generic type PropertyType:

type PropertyType < T > =
    T extends Property.ENABLED ? boolean :
    T extends Property.SIZE    ? number  : any;

и изменил функцию подпись:

getProperty<T extends Property>(property : T) : PropertyType<T>

Это отлично работает, если я вызываю функцию с новым string enum:

const enabled: boolean = getProperty(Property.ENABLED);

Но если я вызываю функцию с простой строкой (необходимо для обратного совместимость) вот так:

const enabled: boolean = getProperty("enabled");

Я получаю следующую ошибку:

Argument of type '"enabled"' is not assignable to parameter of type 'Property'.(2345)

Есть ли хороший способ поддержки обоих способов (string и string enum) для передачи параметр свойства?

Мой пример также доступен здесь: Машинописная площадка

1 Ответ

1 голос
/ 07 мая 2020

Вы можете перегрузить функцию или сделать параметр типа getProperty типом объединения.

Перегрузка:

function getProperty(property: string): any;
function getProperty<T extends Property>(property : T) : PropertyType<T>
{
    return store[property];
}

Тип объединения:

function getProperty<T extends Property | string>(property : T) : PropertyType<T>
{
    return store[property];
}

Полный код:

//Example Value store
const store: { [key: string]: any } = {
    "enabled": true,
    "size": 4
};

//--------------------------------------------------------------------------

//String Enum Property
enum Property {
    ENABLED = 'enabled',
    SIZE    = 'size'
}

//--------------------------------------------------------------------------

//Property Types
type PropertyType < T > =
T extends Property.ENABLED ? boolean :
T extends Property.SIZE    ? number  : any;

//--------------------------------------------------------------------------

// Generic getProperty function
 function getProperty<T extends Property | string>(property : T) : PropertyType<T>
    {
        return store[property];
    }

//--------------------------------------------------------------------------

const enabled0: boolean = getProperty(Property.ENABLED);
const enabled1: boolean = getProperty('enabled');

Другой способ - просто выбрать другое имя функции, поскольку вы не получаете никакой безопасности типов от перегрузки. Я думаю, это лучший вариант для сохранения обратной совместимости.

...