2021年3月7日星期日

Dealing with Unwrapped Variadic Tuple Types

Consider the following code:

interface Wrap<Value> {    pick(): Value  }    class WrapConstant<Value> implements Wrap<Value> {    constructor(public readonly a: Value) { }    pick(): Value { return this.a }  }    type Unwrap<Wrapped> = { [P in keyof Wrapped]: Wrapped[P] extends Wrap<infer Value> ? Value : never }    class WrapTuple<Tuple extends Wrap<unknown>[], Value = Unwrap<Tuple>> implements Wrap<Value> {    readonly ts: Tuple    constructor(...t: Tuple) { this.ts = t }      pick(): Value { return this.ts.map(a => a.pick()) }                // fails to type check  }    type T1 = Unwrap<[WrapConstant<number>, WrapConstant<string>]>       // [number, string]    new WrapTuple(new WrapConstant(1), new WrapConstant("hello")).pick() // [1, "hello"]  

Basically I'm unwrapping a tuple which I know to follow a certain shape (tuple of Wrap<Values>). The pick() function in WrapTuple is supposed to guarantee the return of the same shape of the unwrapped types (provided by Unwrap<Tuple>), although I get a type check error in that line. Questions:

  1. Is this because Unwrap<Tuple> is not guaranteed to have the same shape due to the conditional type inference?
  2. Is it possible to make it work without forcing a cast as unknown as Value?

Update: As commented by Linda, mapping a tuple does not result in a tuple. I tried merging my own declaration for map as suggested here:

interface Array<T> {    map<U>(callbackfn: (value: T, index: number, array: T[]) => U,            thisArg?: any): { [K in keyof this]: U }  }  

But this still requires the map to be asserted to Value:

pick(): Value { return this.ts.map(a => a.pick()) as Value }  
https://stackoverflow.com/questions/66519270/dealing-with-unwrapped-variadic-tuple-types March 08, 2021 at 01:20AM

没有评论:

发表评论