I'm using a TypeScript type guard in a ternary operator within a loop and seeing a behavior I don't understand.
My interfaces
interface INamed {
name: string;
}
interface IOtherNamed extends INamed {
otherName: string;
}
My type guard
function isOther(obj: any): obj is IOtherNamed {
... // some check that returns boolean
}
General Usage Sample
var list: Array<{named: INamed}> = [];
for(let item of list) {
var other: IOtherNamed = ...
}
Inside of my for .. of loop I am using my type guard to assign either my current item or null to a variable of IOtherNamed.
This doesn't work
// Compiler Error: INamed is not assignable to IOtherNamed
for(let item of list) {
var other: IOtherNamed = isOther(item.named) ? item.named : null;
}
This does
for(let item of list) {
var named: INamed = item.named;
var other2: IOtherNamed = isOther(named) ? named : null;
}
My Questions
A type guard is a TypeScript technique used to get information about the type of a variable, usually within a conditional block. Type guards are regular functions that return a boolean, taking a type and telling TypeScript if it can be narrowed down to something more specific.
What does ?: mean in TypeScript? Using a question mark followed by a colon ( ?: ) means a property is optional. That said, a property can either have a value based on the type defined or its value can be undefined .
The in operator narrowing JavaScript has an operator for determining if an object has a property with a name: the in operator. TypeScript takes this into account as a way to narrow down potential types. For example, with the code: "value" in x . where "value" is a string literal and x is a union type.
In Typescript, Type aliases give a type a new name. They are similar to interfaces in that they can be used to name primitives and any other kinds that you'd have to define by hand otherwise. Aliasing doesn't truly create a new type; instead, it gives that type a new name.
Yes, this is by design for TypeScript < 2.0:
Note that type guards affect types of variables and parameters only and have no effect on members of objects such as properties.
— 4.20 from the language specification (PDF, page 83)
So the reason it works in the second scenario is because you have assigned the property to a variable and then type guarded that variable.
Update: As Alex pointed out, TypeScript 2.0 will support type guards on properties.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With