TypeScript'te Jenerikler: Fonksiyonlarda Jenerik Kullanımı


Typescript kodum aşağıdaki gibi: (typescript 4.4 içinde)

export function convert<T extends (...args: any[]) => any>(
    func: T
): (_this: ThisParameterType<T>, ...args: OmitThisParameter<Parameters<T>>) => ReturnType<T> {
    return Function.call.bind(
        Function.bind,
        Function.call
    )(func) as (_this: ThisParameterType<T>, ...args: OmitThisParameter<Parameters<T>>) => ReturnType<T>;
}

ama bunu böyle kullandığımda:

// mark 1
const arrayShift = convert([].shift);
// expect: const shifted: string
const shifted = arrayShift(["1"]); // const shifted: undefined

// mark 2
const arrayMap = convert([].map);
// expect (parameter) e: string
arrayMap(["1"], (e) => { // (parameter) e: never
    return parseInt(e, 10);
});

İsmi 'convert' olan fonksiyonu değiştirerek beklenen tipe nasıl ulaşılır?

Cevap #1

Bunu 2 adımlı bir yaklaşımla başarmayı başardım. convert bir fonksiyon döndürür, bu fonksiyonu ister argümanlarla ister argümansız çağırabilirsiniz.

oyun alanını gör

function convert<A extends Array<T>, T extends any, K extends keyof Array<T>>(
  array: A extends Array<infer U> ? Array<U> : Array<T>,
  key: K,
) {
  function convertArray<A extends Array<T>, T extends any>(
    array: A extends Array<infer U> ? Array<U> : Array<T>,
    key: K,
  ) {
    return array[key]
  }
  return function<S extends Array<Y>, Y extends any>(
    subjectedArray: S extends Array<infer SK> ? Array<SK> : Array<Y>,
    args?: any[] // not yet figured out to call convertArray with args and keep types
  ) {
    return (convertArray<S, Y>(
      subjectedArray,
      key
    ))
  }
}

const arrayShift = convert([], 'shift')
const arrayMap = convert([], 'map')

const empty = arrayShift([])() // const empty: undefined
const shifted = arrayShift(["123"])() // const shifted: string | undefined
const mapped = arrayMap(["1"])(e => { // (parameter) e: string
  return parseInt(e, 10);
}) // const mapped: number[]

type Car = {
  engine: 'petrol' | 'gasoline'
}
const cars: Car[] = []
const emptyCars = arrayShift(cars)() // const emptyCars: Car | undefined

İlgili makaleler