简体   繁体   中英

How to add types for a typescript function that takes in an array of generics

please see code sample below- i'd like some typesafety around the type of array entries that resetHistory takes in, but it's not creating a type error where i'd like it to. appreciate any tips.

typescript playground link

type Params = {
  profile: { userId: string };
  homepage: undefined;
  settings: { tab: "password" | "profile" };
};

// naive attempt at typing the history arg
function resetHistory<K extends keyof Params>(
  history: { name: K; params: Params[K] }[]
) {
  // ...
}

resetHistory([
  { name: "homepage", params: undefined },
  { name: "profile", params: { userId: "1234" } },
  { name: "settings", params: { userId: "xxx" } }, // <-- i want this to be a typeerror, and only accept { tab: "password" | "profile" }
]);

What you need here is a union of all possible pairings. We can create that with a mapped type.

type HistoryEntry = {
  [K in keyof Params]: Params[K] extends undefined 
      ? { name: K; params?: undefined; }
      : { name: K; params: Params[K]; }
}[keyof Params]

For each key of the Params object, the acceptable value is an object with a name that matches that key and a params that matches the Params value for that key. That is { name: K; params: Params[K]; } { name: K; params: Params[K]; } { name: K; params: Params[K]; } .

I am adding a conditional check Params[K] extends undefined to allow you to omit the params entirely if they are undefined . So you can just pass { name: "homepage" } .

Our resetHistory function is no longer generic. It accepts an array where all entries are of type HistoryEntry .

function resetHistory( history: HistoryEntry[] ) {

This gives us all of the errors that we want:

resetHistory([
  { name: "homepage" }, // ok
  { name: "profile", params: { userId: "1234" } }, // ok
  { name: "settings" }, // error: params is missing
  { name: "settings", params: { userId: "xxx" } }, // error: tab is missing from params
  { name: "settings", params: { tab: "password" } } // ok
]);

Typescript 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