[Typescript] Be Specific for Better Inference
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'>>>
];
相关文章
- [Typescript Challenges] 10. Medium - Include
- [TypeScript] ReturnType
- [React Typescript 2022] Refactor a React Component using TypeScript
- [Typescript] Dynamic types: Use TypeScript's Mapped Types and Template Literal Types Together
- [Typescript] Ignore Null or Undefined Values with TypeScript Non-Null Assertion Operator
- [Typescript] Extend Functionality of a TypeScript Class with Decorators
- [Typescript] Understanding “lib” and ES libraries
- [Vuex] Use Namespaces in Vuex Stores using TypeScript
- [React] Write a stateful Component with the React useState Hook and TypeScript
- [TypeScript] Dynamically Allocate Function Types with Conditional Types in TypeScript
- [TypeScript] Use TypeScript’s never Type for Exhaustiveness Checking
- [Typescript] Generics using TypeScript
- [TypeScript] Using Assertion to Convert Types in TypeScript
- [TypeScript ] What Happens to Compiled Interfaces
- [Typescript] Declaring Globals for a Library
- [Typescript] Approaches for Typing Object Parameters
- [Typescript] Simplify iteration of custom data structures in TypeScript with iterators (backwards iteration with for ... of.. loop)
- [TypeScript] Use the JavaScript “in” operator for automatic type inference in TypeScript
- [Typescript] Sorting arrays in TypeScript
- typescript ts接口简单示例
- TypeScript 里 object 和 Object 的区别
- Vue+TS/Typescript:Property does not exist on type ‘(() => any) | ComputedOptions<any>‘
- 掌握TypeScript:10个最佳实践提高代码质量