-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Suggestion: explicit type narrowing #9946
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
+1 for this feature. I was also thinking of another way to have "type assertion type" assertion work in interface Yo {
type: 'yo';
}
let foo: any;
if ((foo.type === 'yo') as foo is Yo) {
// Now `foo` has type `Yo`.
} |
the example with function isElement(node: Node): node is Element { return node.nodeType === 1; } what is wrong with defining a super-small function for it? i think that using
|
I think the unboundedness can help sometimes with its flexibility. What about this: // jQuery ajax
$.ajax({
url: "http://example.com/foo.xml",
dataType: "xml"
}).then(data => {
// data is any
declare data: XMLDocument; // I know better than the type system!
}); PS: Specifically, I posted this suggestion because I had to catch an error and get error type. try {
/* ... */
}
catch (err) {
if (isWebIDLParseError(err)) {
const werr = err as WebIDL2.WebIDLParseError; // type narrowing does not work :(
console.warn(`A syntax error has found in a WebIDL code line ${werr.line} from ${result.url}:\n${werr.input}\n`);
}
else {
throw new Error(`An error occured while converting WebIDL from ${result.url}: ${err.message || err}`);;
}
} |
first: narrowing from the interface Request<Data> {
url: string;
dataType: string;
}
function fetchData<Data>(request: Request<Data>) : Promise<Data> {
return $ajax(request);
}
const request: Request<XMLDocument> = {
url: "http://example.com/foo.xml",
dataType: "xml"
};
fetchData(request).then(xml => { /* xml is XMLDocument */ }) |
@saschanaz see also #8677
@Aleksey-Bykov amen, same here. The compiler treats For me the best of both world would be that After all, an explicit type cast does work on But it's not going to happen because it's too much of a breaking change to make people change the annotation of // By contract, this function accepts only a Dog or a House
function fn(x: any) {
// For whatever reason, user is checking against a base class rather
// than the most-specific class. Happens a lot with e.g. HTMLElement
if (x instanceof Animal) {
x.woof(); // Disallowed if x: Animal
} else {
// handle House case
}
} If TypeScript accepted a breaking change here with the advice to use a union type annotation rather than
...then let them work with
...except be narrowed even when explicitly requested |
@yortus i've ranted a bit right past that example you mentioned, i have a strong opinion about the shady business that is going on there |
@Aleksey-Bykov your rant is spot on. Shady business indeed. |
related #9999 |
( @rozzzly deleted post by mistake, original post: #9946 (comment) ) Great, and I think this can be better for boundedness sake. function foo(x: any) {
// type of x is `any`
if (someCondition): x is number[] { // doesn't matter what this is
// now type of x is `number[]`
x.push (7);
}
// type of x is `any`
} |
I accidentally deleted my post prior to saschanaz's because the buttons on my phone are so small. 😡 This is what it said: I've always wanted something like function foo(x: any) {
// type of x is `any`
if (someCondition) { // doesn't matter what this is
// type of x `any`
x is number[];
// type of x is `number[]`
x.push(7);
}
// type of x is `any`
} I think this would be a good fit! It's simple and looks/behaves like a type guard. It seems like a natural extension of the concept. Unfortunatly, @saschanaz ooh that's nice too, definitely helps by defining the scope within which that type has been narrowed. But, I think adding it to an oh and what about this... function foo(x: string | number) {
// type of x is `string | number`
if (someCondition): x is string {
console.log(x.toUpperCase()); // valid because we know x is a string
} else {
// typeof x is `string | number`
// someone could get confused here and think that x is a
// `number` like you can do with type guards on unions
// but the condition very well might depend on something
// other that the type of x being a string for example
if (true === false && _.isString(x)): x is string {
// will never occur because true !== false
} else {
// x could still be a string.
}
}
} |
That problem also occurs with type guard functions. function isString(something: any): something is string {
return true === false && _.isString(x)); // ???
} |
Let's track this at #10421 |
To fix #5930 and #6474:
Syntax and use cases
Behavior
Why not existing type guards?
any
type cannot be narrowed by type guards. (User defined type guard function and type any #5930)Workaround
Declare a new variable.
var element = node as Element
The text was updated successfully, but these errors were encountered: