zl程序教程

您现在的位置是:首页 >  前端

当前栏目

[Typescript] Be Specific for Better Inference

typescript for be Better specific Inference
2023-09-14 08:59:11 时间

This exercise begins with a makeStatus function that takes in an array of TStatuses that extends an array of strings. The statuses are then returned, kind of like an identity function:

const makeStatus = <TStatuses extends string[]>(statuses: TStatuses) => {
  return statuses;
};

Looking at the tests, we can see that we're expecting statuses to be an array of INFO or DEBUG or ERROR or WARNING, all of the things that we pass in here.

const statuses = makeStatus(["INFO", "DEBUG", "ERROR", "WARNING"]);
//    ^?  string[]
type tests = [
  Expect<Equal<typeof statuses, Array<"INFO" | "DEBUG" | "ERROR" | "WARNING">>>, // not working
];

However that's not what we're getting-- instead, we just get an array of strings.

 

So idea is to get actual value of each string array memeber. 

In Typescript compiler, if you use generic on array level, then it infer typeof this array

["INFO", "DEBUG", "ERROR", "WARNING"] // string[]
["INFO", "DEBUG", "ERROR", 1] // (string | number)[]
[1,2,3,4] // number[]
[1,2,3,undefined] //(number | undefined)[]

 

So, if you want to get so array member as type, you have to go deeper, which means, the generic type cannot be array level any more, it needs to be array member level.

const makeStatus = <TStatus extends string>(statuses: TStatus[]) => {
  return statuses;
};

So we got correct results.

const statuses = makeStatus(['INFO', 'DEBUG', 'ERROR', 'WARNING']);
//     ^?  ("INFO" | "DEBUG" | "ERROR" | "WARNING")[]
type tests = [
  Expect<Equal<typeof statuses, Array<'INFO' | 'DEBUG' | 'ERROR' | 'WARNING'>>>
];

 

If we change the array to be (number | string)[]

const makeStatus = <TStatus extends string | number>(statuses: TStatus[]) => {
  return statuses;
};

const statuses = makeStatus([1, 'DEBUG', 'ERROR', 'WARNING']);
//     ^?  (1 | "DEBUG" | "ERROR" | "WARNING")[]
type tests = [
  Expect<Equal<typeof statuses, Array<1 | 'DEBUG' | 'ERROR' | 'WARNING'>>>
];