2016-11-01 5 views
1

Я заметил проблему, когда пользовательский тип защиты от типа объединения не ведет себя симметрично. Я надеюсь, что это ошибка на моем конце: -/Является ли это ошибкой в ​​компиляторе Typcript

Проблема возникает в test2(), где тип не выводится должным образом из типаguard.

class PropPacket { 
    constructor(public key: string, public value: number) {} 
} 

class EventPacket { 
    constructor(public key: string) {} 
} 

type Packet = PropPacket | EventPacket; 

function isPropPacket(p: EventPacket | PropPacket): p is PropPacket { 
    return p instanceof PropPacket; 
} 

function isEventPacket(p: EventPacket | PropPacket): p is EventPacket { 
    return p instanceof EventPacket; 
} 

function test1(p: Packet) { 
    if (isPropPacket(p)) { 
     // `p` is PropPacket 
     p.key; 
     p.value; 
    } else { 
     // `p` is EventPacket 
     p.key; 
    } 
} 

function test2(p: Packet) { 
    if (isEventPacket(p)) { 
     p.key; 
    } else { 
     // ERROR: thinks `p` is `never` type 
     p.key; 
     p.value; 
    } 
} 

Вы можете увидеть проблему, скопировав код в машинописи игровой площадке (https://www.typescriptlang.org/play/)

+0

Интересно. Я не юрист по языку, но для чего он стоит, он ведет себя так, как вы ожидали, если вы переименуете свойство 'key' в любом из типов« Packet »на что-то еще, например. 'Key2'. – cynic

ответ

1

Это происходит потому, что все EventPacket s фактически PropertyPacket с. У машинописного машиностроения есть структурная система типов, которая не учитывает два класса, которые могут быть разными по декларации, только по содержащимся в них свойствам и методам.

+0

Хммм - похоже, ты прав. Если я добавлю неиспользуемое частное свойство в объявление EventPacket, оно решает проблему. Угадайте, что это уродливый побочный эффект системы. – bjnsn

+0

Я бы не сказал, что это обязательно плохо. С одной стороны, это не соответствует поведению во время работы (плохо), с другой стороны, он не поддерживает этот тип кода (хороший). –

Смежные вопросы