Home > database >  Typescript def for object value that returns extended generic
Typescript def for object value that returns extended generic

Time:01-30

I have a feeling this isn't possible, but I figure I ask. I defined the following:

type Params<TState> = {
    init?: (arg: TState) => TState;
}

function getInit<TState> (params: Params<TState>) {
    return params.init
}

const state = {
    h: 1,
}
const init = getInit<typeof state>({
    init: (initState) => ({
        ...initState,
        d: 'd'
    })
});
type INIT = typeof init;

The problem is INIT returns

type INIT = ((arg: {
    h: number;
}) => {
    h: number;
}) | undefined

when it should return

type INIT = ((arg: {
    h: number;
}) => {
    h: number;
    d: string; // THIS IS MISSING
}) | undefined

and I don't know how to define Params to show the extended return value.

here's the playground link if you want to play around with this https://www.typescriptlang.org/play?#code/C4TwDgpgBACghgJzgWwM4B4AqBlYdgQB8UAvFAN4BQUNUAlgHZ3AD8AXFABSIDmHOeAgEpSxAfggBuSgF9KlAGYBXBgGNgdAPYMoPCMACSTYFlwTinMIhSoO8JGlOCiIqrSgJ9ShDqsPUAHSMzLLyqtqowFCREqQU1LQAFhwAjAA0oeEMkfTGcXqGxuigkJoK0c6EnG60wcAcnHVmwqJcNe40AV1NzhkdtAAmHADkA8MJNDJCskLSlCXQBgByBphxC2W5zJJAA

CodePudding user response:

If the args to init and the return value are different types, then they should be different types.

It sounds like you want to take any input type, and then allows the function to return a value of a type that extends the input type. So that's two generic parameters, not just one.

That makes the Params type look like this:

type Params<
    TStateInput,
    TStateOutput extends TStateInput
> = {
    init?: (arg: TStateInput) => TStateOutput;
}

Now the TStateInput type can be your args, and TStateOutput can be the return value with whatever extra properties are added.

getInit now would like this:

function getInit<
    TStateInput,
    TStateOutput extends TStateInput
> (params: Params<TStateInput, TStateOutput>) {
    return params.init
}

Playground

CodePudding user response:

As an alternative to @alex-wayne answer: this will not give you exactly what you want (you can't have that) but may fit your requirements:

Define TState as

type TState ={
    h:number,
    [key:string]: string | number
}
  •  Tags:  
  • Related