TypeScript Условные типы и охранники типов - PullRequest
0 голосов
/ 27 ноября 2018

У меня возникли некоторые проблемы при объединении типов защиты TypeScript и условных типов.Рассмотрим:

export interface IThisThing {
    someProp: number;
}

export function isIThisThing(type: any): type is IThisThing { 
    return !!type.someProp;
}

export interface IThatThing {
    someOtherProp: string;
}

export function isIThatThing(type: any): type is IThatThing { 
    return !!type.someOtherProp;
}

function doAThing<T extends IThisThing | IThatThing>(
    data: T
): T extends IThisThing ? IThisThing : IThatThing {
    if (isIThisThing(data)) { 
        return data; // Type 'T & IThisThing' is not assignable to type 'T extends IThisThing ? IThisThing : IThatThing'.
    };
    return data; // Type 'T' is not assignable to type 'T extends IThisThing ? IThisThing : IThatThing'.
                 //   Type 'IThisThing | IThatThing' is not assignable to type 'T extends IThisThing ? IThisThing : IThatThing'.
                 //     Type 'IThisThing' is not assignable to type 'T extends IThisThing ? IThisThing : IThatThing'.
}

Я бы ожидал, что функция doAThing примет IThisThing или IThatThing и вернет тот же тип, что и при получении.Увы, компилятор захлебывается сообщениями в виде строк:

Type 'T & IThisThing' is not assignable to type 'T extends IThisThing ? IThisThing : IThatThing'.

Может кто-нибудь меня поправить?Я чувствую, что я близко, но не совсем понимаю это правильно.Я использую первый пример (который кажется довольно похожим) в этом посте: http://artsy.github.io/blog/2018/11/21/conditional-types-in-typescript/

1 Ответ

0 голосов
/ 27 ноября 2018

Typescript не позволит вам присвоить что-либо условному типу, у которого все еще есть параметр свободного типа, он просто не поддерживается.Лучше всего иметь подпись с обобщениями и условным типом, а также более простую подпись реализации, которая возвращает объединение двух возможностей

export interface IThisThing {
    someProp: number;
}

export function isIThisThing(type: any): type is IThisThing { 
    return !!type.someProp;
}

export interface IThatThing {
    someOtherProp: string;
}

export function isIThatThing(type: any): type is IThatThing { 
    return !!type.someOtherProp;
}

function doAThing<T extends IThisThing | IThatThing>(
    data: T
): T extends IThisThing ? IThisThing : IThatThing
function doAThing(
    data: IThisThing | IThatThing
): IThisThing | IThatThing {
    if (isIThisThing(data)) { 
        return data;
    };
  return data;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...