-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Description
TypeScript Version: 4.1.0-insiders.20201007
Search Terms:
type guard generics
Code
interface IndexedObject {
[key: string]: any
}
/**
* Check if the value is a "plain" JavaScript object initialized with { } (not instance of any class)
*
* In addition to the runtime check, this function should assert that the
* argument matches IndexedObject interface
*
*/
const isPlainObject = (value: any): value is IndexedObject => (
typeof value === 'object'
&& value !== null
&& value.constructor === Object
&& Object.getPrototypeOf(value) === Object.prototype
);
function genericFunction<T>(value: T): T {
if (isPlainObject(value)) {
type x = typeof value; // T - not quite right
return value;
}
type x = typeof value; // "never"
return value;
}
function normalFunction(value: any): void {
if (isPlainObject(value)) {
type x = typeof value; // IndexedObject - ok
}
type x = typeof value; // any - ok
}Expected behavior:
Inside genericFunction() in the if block, the type of value should be T & IndexedObject. After the if block, the type of value should be x
Actual behavior:
Inside the genericFunction(), in the if block, type of value is T, and after the if block - type of value is never. It works ok in a non-generic function
Comment
I am aware that this is not an ideal use case. "plain object" as I defined it, is not strictly tied to IndexedObject interface - which might cause unexpected problems with types. I have decided to not use a type guard for this function, nevertheless - I wanted to submit this as it seems to be a bug. I could not reproduce a more "generic" example.