简体   繁体   中英

TypeScript: Infer type of parameter with default value

4ex, here is the code i have now

type Validity = [any, ...any[]];

interface StateValidator<V extends Validity, S> {
  (state: S): V;

  (state: S, dispatch: (validity: V)=>void): void;
}

function validate<V extends Validity, S, I extends Validity>(
    state: S,
    validator: StateValidator<V, S>,
    initialValidity: I = [null]
): I | V { 
    return initialValidity;
}

Playground Link

Body of validate function is omitted but the sense here is that in the beginning return value always the initialValidity and then it is what validator returns. Furthermore, validity should be an array with 1st element of any type and arbitrary amout of rest elements of any type.

In current implementation i have an error:

Error:(16, 3) TS2322: Type '[null]' is not assignable to type 'I'.
  '[null]' is assignable to the constraint of type 'I', but 'I' could be instantiated with a different subtype of constraint 'ValidityState'.

As i understand it, I should infer the type of argument but why do i get that error and how to achieve what i want?

I want it to have next types:

validate(number, (_: any) => [boolean | null, number]);
// [boolean | null, number] | [null]

validate(number, (_: any) => [boolean | null], [undefined]);
// [boolean | null, number] | [undefined]

As discussed in this TypeScript github issue and described in this SO answer , this error is logically correct for more generic cases. And your case is not resolved in TS now.

I can suggest this solution:

type Validity = [any, ...any[]];

interface StateValidator<V extends Validity, S> {
  (state: S): V;

  (state: S, dispatch: (validity: V)=>void): void;
}

function validateWithInitial<V extends Validity, S, I extends Validity>(
    state: S,
    validator: StateValidator<V, S>,
    initialValidity: I
): I | V { 
    return initialValidity;
}

function validate<V extends Validity, S>(
    state: S,
    validator: StateValidator<V, S>
): [null] | V { 
    const initialValidity: [null] = [null];
    return initialValidity;
}

Playground link

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM