Skip to content

Let us intersect the type of a function argument based on the value of another argument #41233

@AnmSaiful

Description

@AnmSaiful

Here is a basic User class:

class User< U > {

    private _user: Partial< U > = {};

    public set< K extends keyof U >(

        key: K,
        val: U[ K ],

    ) : void {

        this._user[ key ] = val;

    }
}

And a basic Employee interface:

interface Employee {

    name: string;
    city: string;
    role: number;

}

Now, consider the following implementation:

const admin = new User< Employee >();

admin.set( "name", 10 );

The above script yields the following error which is expected.

Argument of type 'number' is not assignable to parameter of type 'string'.

Now take a look at the following implementation:

const admin = new User< Employee >();

admin.set< "name" | "role" >( "name", 10 );

The above script does not yield any error and it is also expected, as long as 10 is assignable to name or role.

To make it more clear, let's take a look at the following script:

const admin = new User< Employee >();

admin.set< "name" | "role" >( "name", true );

The above script yields the following error which is also expected.

Argument of type 'boolean' is not assignable to parameter of type 'string | number'.


Now, what I want to achieve is, 10 should not be allowed to be stored as a value of name at any mean.

For this, I need to make some changes to my code something similar to the followings:

public set< K extends keyof U >(

    key: K,
    val: U[ valueof key ],

) : void {

    this._user[ key ] = val;

}

But as long as there is nothing like valueof key, this cannot be achieved dynamically.

For testing, if you replace U[ K ] by U[ "name" ], you will see 10 is no longer allowed anymore at any form.

Many programmers solved similar problems by applying T[ keyof T ] which I think is not applicable to this case.

Thanks in advance.

Playground

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions