The following code suggests to me that even though I specify a union type for a variable instead of one of the types making up the union, that tsc uses the specific type for a variable.
This code fails to compile with TypeScript 3.9.2:
src/test.ts:49:25 - error TS2339: Property 'language' does not exist on type 'never'.
The intersection 'CommandNotSelected & SayHelloCommand' was reduced to 'never' because property 'commandType' has conflicting types in some constituents.
35 console.log(command.language);
enum CommandType {
SAY_HELLO,
COMMAND_NOT_SELECTED,
}
interface SayHelloCommand {
commandType: CommandType.SAY_HELLO;
language: string;
}
interface CommandNotSelected {
commandType: CommandType.COMMAND_NOT_SELECTED;
}
type Command = SayHelloCommand | CommandNotSelected;
function isSayHelloCommand(c: Command): c is SayHelloCommand {
return c.commandType === CommandType.SAY_HELLO;
}
let command: Command = {
commandType: CommandType.COMMAND_NOT_SELECTED,
};
function f() {
command = {
commandType: CommandType.SAY_HELLO,
language: 'foobar',
};
}
f();
if (isSayHelloCommand(command)) {
console.log(command.language);
}
I can get this to compile by swapping out the code to
function initialCommand(): Command {
return {
commandType: CommandType.COMMAND_NOT_SELECTED,
};
}
let command = initialCommand();
or
let command: Command = {
commandType: CommandType.COMMAND_NOT_SELECTED,
} as Command;
I assumed that TypeScript would use Command for the type instead of CommandNotSelected and modify its type as it sees modifications to the command.