Closed
Description
TypeScript Version: 3.9.0--dev.20200319
Search Terms: assertion condition, narrow assertion condition, assertion condition union
Code
type MyUnion = { [key: string]: any } | string[];
function assertObject(value: any): asserts value is Record<string, any> {
if (value === null || typeof value !== "object" || Array.isArray(value)) {
throw new Error("Assertion failed");
}
}
function getValue(): MyUnion {
return { foo: "bar" };
}
const value = getValue();
assertObject(value);
// Error as it does not know if it is a string[] or { [key: string]: any }
console.log(value["propName"]);
I've also observed that TypeScript is using the already known type at caller (i.e. MyType
) to narrow after the assert function is called. This is resulting in never
as a result.
I am not sure this part is behaving as expected, but seems to be related to the bug reported.
type MyType =
| {
[key: string]: {
[k: string]: number;
};
}
| string;
const a: MyType = { foo: { bar: 123 } };
function assertUndefined(value: any): asserts value is undefined {
if (value !== undefined) throw new Error();
}
assertUndefined(a.foo);
// `a.foo` is `never`
console.log(a.foo);
Expected behavior: assert condition should narrow the type to one of the values in the union.
Actual behavior: it seems to be merging what is knows about the type at the caller with what the assertion returns.
Related Issues: #37241