Home > front end >  TypeScript: Generic strange behaviour
TypeScript: Generic strange behaviour

Time:12-19

I have the following code:


export type Primitive = boolean|string;
export type ObjectItem = {[k: string]: ObjectItem|Primitive}; 
export type DynamicItem<T extends ObjectItem|Primitive> = T extends ObjectItem ? ObjectItemInterface<T> : PrimitiveItemInterface<T>;
export interface PrimitiveItemInterface<T extends (ObjectItem|Primitive)> {
    value(): T;

    set(v: T): void;
}

export interface ObjectItemInterface<T extends ObjectItem> extends PrimitiveItemInterface<T> {
    get<K extends keyof T>(k: K): DynamicItem<T[K]>;
}

const example: ObjectItemInterface<{
    enabled: boolean
}> = null;

example.get('enabled').set(true); //Argument of type 'boolean' is not assignable to parameter of type 'never'.ts(2345)

Why it thinks that there is never type?

I want it to see the boolean type.

CodePudding user response:

The problem is that you use boolean as a naked parameter type, which makes it used as enter image description here

solution is to stop the distributive behavior

export type DynamicItem<T extends ObjectItem | Primitive> = [T] extends [ObjectItem] ? ObjectItemInterface<T> : PrimitiveItemInterface<T>;

enter image description here

//=======Update=========

I found the explanation why OP got never, explanation I quote from discord:

when you declare a type, the inferred parameter types on the function do not override
so v can be any in the function literal (because typescript is refusing to infer from the union type A)
but when you call a, typescript does the true & false = never and refuses to allow you call `a`

enter image description here playground

  • Related