выведите функцию, возвращающую тип, зная значение одного свойства - PullRequest
3 голосов
/ 05 мая 2019

Есть ли способ сделать это? Я знаю, что я могу if / else или переключить мое свойство type для получения определенного интерфейса. Но можно ли сделать что-то подобное с возвращаемым значением функции (или метода)?

interface test1 {
    type: 'test1'
}

interface test2 {
    type: 'test2'
}

type unType = test1 | test2;

//i know property "type"'s value
//can i somehow use this information to infer specific type (test1 or test2)
function whichType<T>(typeValue): T {

    return null;
}

const tt1 = whichType<unType>('test1');// should be interface test1
const tt2 = whichType<unType>('test2');// should be interface test2

Ответы [ 2 ]

3 голосов
/ 05 мая 2019

Вы можете использовать перегрузки, как предполагает TJ Crowder, и это, вероятно, лучшее решение, если у вас всего несколько интерфейсов, так как написать простое понимание просто.

Более общим решением было бы использование условного типа Extract для извлечения типа на основе строки, переданной в:

interface test1 { type: 'test1' }

interface test2 { type: 'test2' }

type unType = test1 | test2;

function whichType<K extends unType['type']>(typeValue: K): Extract<unType, {type: K}> {
    return null!;
}

const tt1 = whichType('test1'); // test1
const tt2 = whichType('test2'); // test2

Решение, которое будет работать для любого объединения, может быть построено, но оно требует использования функции каррирования, потому что машинопись не поддерживает частичный вывод параметров типа:

function whichType<T extends { type: string}>() {
    return function <K extends T['type']>(typeValue: K): Extract<T, {type: K}> {
        return null!;
    }
}

const tt1 = whichType<unType>()('test1'); // test1
const tt2 = whichType<unType>()('test2'); // test2
2 голосов
/ 05 мая 2019

Вы можете сделать это с точки зрения типа, если вы действительно используете литералы при вызове whichType, используя перегрузку функций:

interface test1 {
    type: 'test1'
}

interface test2 {
    type: 'test2'
}

type unType = test1 | test2;

function whichType(typeValue: 'test1'): test1;
function whichType(typeValue: 'test2'): test2;
function whichType(typeValue: string): unType {
    switch (typeValue) {
        case 'test1':
            return <test1>null;
        case 'test2':
            return <test2>null;
        default:
            throw new Error(`Unknown type ${typeValue}`);
    }
}

const tt1 = whichType('test1'); // tt1's type is test1
const tt2 = whichType('test2'); // tt2's type is test2

На игровой площадке

Как видно из комментария к коду, вам все еще понадобится логика времени выполнения для его обработки во время выполнения.

Чтобы разрешить не буквальные строки в вызовах whichType, вам нужно добавить еще однуперегрузка:

function whichType(typeValue: string): unType;

... и затем имейте дело с тем фактом, что вы не знаете тип.: - |

[На игровой площадке] [2]

[2]: функция whichType (typeValue: string): unType;

...