typescript - Videreføre typeparametere til generisk type når man implementerer generisk funksjon


Si at jeg får en funksjonstype som dette. Jeg kan allerede implementere en funksjon av den typen, og trenger ikke å erklære argument- eller returtypene igjen:

type MyFunc = (args: string) => boolean;

// TS knows args is a string and return is boolean 👍
const myFunc: MyFunc = (args) => true;

Men, si at jeg får en generell funksjonstype. Jeg vil implementere en funksjon som følger denne typen, men videreføre de generiske typeparameterne til anroperen. Er dette mulig? Forsøket mitt gir en feil:

type ReturnsSomething<A> = (args: A) => A;

// Generic type 'ReturnsSomething' requires 1 type argument(s).ts(2314)
const logAndReturnSomething: ReturnsSomething = (args) => {
  console.log(args);
  return args;
};

logAndReturnSomething<string>('asdf');

Dette fungerer heller ikke:

type ReturnsSomething<A> = (args: A) => A;

// Cannot find name 'A'.ts(2304)
const logAndReturnSomething: ReturnsSomething<A> = (args) => {
  console.log(args);
  return args;
};

logAndReturnSomething<string>('asdf');

I mer kompliserte tilfeller vil jeg ikke omdefinere argumentene og returtypene i alle mine implementasjoner, da det ødelegger hensikten med en delbar ReturnsSomething generisk. Finnes det en måte å implementere en generisk funksjon som videresender sine typeargumenter til en generisk type?

Jeg kunne lage en wrapper-funksjon for å håndheve denne typen, men det betyr at jeg trenger et dobbelt funksjonskall hver gang jeg bruker den, jeg skulle ønske det var en renere måte:

type ReturnsSomething<A> = (args: A) => A;

function makeLogAndReturnSomething<A>(): ReturnsSomething<A> {
  return (args) => {
    console.log(args);
    return args;
  };
}

makeLogAndReturnSomething<string>()('asdf');

Jeg bruker TypeScript 4.6 for det det er verdt, ikke sikker på om 4.7 vil løse dette eller om det er en TS-syntaks jeg går glipp av.

Svar #1

Prøv dette:

type GenericFn = <A>(args: A) => A;

const logAndReturnSomething: GenericFn = (args) => {
  console.log(args);
  return args;
};

const result = logAndReturnSomething('asdf'); //infers return type as string

I hovedsak lager vi ikke en generisk type, men snarere en generisk funksjon. Det er forvirrende, jeg vet :)

Det finnes en flott kort YouTube-video hvis du vil fordype deg mer.

TS-lekeplass

Relaterte artikler