-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Type-guard-assertion-like syntax does not do anything #5731
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
That's a bug. The type predicate syntax should only be allowed in a return type position. |
@ahejlsberg Can we make it valid? It may allow inline type-guard which will be useful when the custom type guard function (1) only requires one single property check (2) is being used only once. |
I'd like to point out that this is also true with let foo: Node
if ((foo.nodeType === 1) as foo is Element) {
} |
@sandersn can you take a look |
I'll disable this for now because I see one big open question with inline type predicates: How is the variable that is part of the predicate related to the variables mentioned in the expression? For example, is this legal? If so, should any checking occur on the expression with respect to the predicate? let x: number | string;
let y: number;
let num: number;
if(<x is number>(y > 12)) {
num = x;
} |
@sandersn I think your example can be translated to this one, and if this is legal then that should be legal too. let x: number|string;
let y: number;
let num: number;
if (isNumber(x,y)){
num = x;
}
function isNumber(x: number|string, y: number): x is number {
return y > 12;
} |
I tried writing a proposal yesterday but hit a couple big problems. I was asking the wrong question about scope, but the problem is about scope. Here's the proposal. The variable capture question could be resolved by your proposed rewrite to function, but no other expression does that that I know of. Type Predicate ExpressionsA type predicate expression allows you to narrow a union type with a single expression. The syntax is
When the expression is used in a conditional context, the true branch of the conditional narrows variable to type, while the false branch narrows variable by removing type. The type predicate expression is of type Boolean, with apparent type of type predicate. The right hand side must be an expression of type Boolean. The left hand side's variable must be a name bound in the current scope. The left hand side's type must be a name bound in the current scope. Open questions
|
function foo(x) {
return isNumber(x); // This currently does not implicitly make `foo` a type predicate
}
function isNumber(x: string|number): x is number {
return typeof x === "number";
} |
Here's an example of what I'm thinking about with (1): function foo() {
const x: number | string = 12;
return <x is number>(typeof x === "number");
}
if(foo()) {
// in this block, x is number. What does that even mean?
} |
I think returning type predicate expressions should just make them normal Booleans. It will make them consistent with current type predicates. function foo() {
const x: number | string = 12;
return isNumber(x); // this makes the return type of `foo` just boolean
function isNumber(x) {
return typeof x === "number";
}
}
if (foo()) {
// nothing special happens
} const x: number | string = 12;
function foo() {
let xIsNumber = <x is number>(typeof x === "number");
if (xIsNumber) {
// x is number
}
return xIsNumber; // Boolean!
}
if (foo()) {
// still nothing happens
} const x: number | string = 12;
function foo() {
return <x is number>(typeof x === "number"); // Maybe future TSLint: this does nothing!
} |
Not sure about alternative syntax. One in my thought:
|
Fixed by #5992. |
The following code does not cause any error nor does type-guard thing.
Is this by design? The language service implicitly thinks the
foo
inside type assertion asany
. I would prefer to making this as a valid type guard syntax if there is no spec about this.The text was updated successfully, but these errors were encountered: