[!Typescript] Tips: dynamic specify the type of arguments to function
typescript to The of type Function Dynamic Tips
2023-09-14 08:59:11 时间
You can use generics to dynamically specify the number, and type, of arguments to functions.
Here, we create a sendEvent
function which only asks for a payload if it's present on the event you're sending.
export type LOGIN = {
type: "LOG_IN";
payload: {
userId: string;
};
}
export type SIGNOUT = {
type: "SIGN_OUT";
}
export type Event =
| LOGIN
| SIGNOUT;
const sendEvent = (eventType: Event["type"], payload?: any) => {};
/**
* Correct
*/
sendEvent("SIGN_OUT");
sendEvent("LOG_IN", {
userId: "123",
});
/**Should error */
sendEvent("LOG_IN", {});
sendEvent("LOG_IN");
Above code doesn't have compile error;
But we want it to has, because "LOG_IN" should has payload, bug "SIGN_OUT" should NOT have payload. It is unsafe to leave the room for error.
Tips:
LOGIN is more speicify, {payload: any} is more loosen... type x is true
type LOGIN = {
type: "LOG_IN";
payload: {
userId: string;
};
}
type x = LOGIN extends {payload: any} ? true : false // true
// Type extends Event["type"] --> "LOG_IN" | "SIGN_OUT"
// Extract<Event, { type: Type } --> will either log LOGIN or SIGNOUT type
// Extract<Event, { type: Type }> extends { payload: infer Payload } --> if the extracted type extends {payload: ...}
// then it we need to require payload as second params
// else we just need type param
const sendEvent = <Type extends Event["type"]>(
...args: Extract<Event, { type: Type }> extends { payload: infer Payload }
? [type: Type, payload: Payload]
: [type: Type]
) => {};
Improved version:
export type LOGIN = {
type: "LOG_IN";
payload: {
userId: string;
};
};
export type SIGNUP = {
type: "SIGN_UP";
payload: {
username: string;
};
};
export type SIGNOUT = {
type: "SIGN_OUT";
};
export type Event = LOGIN | SIGNOUT | SIGNUP;
type SendEventParams<T extends Event["type"]> = Extract<
Event,
{ type: T }
> extends { payload: infer Payload }
? [type: T, payload: Payload]
: [type: T];
const sendEvent = <T extends Event["type"]>(...args: SendEventParams<T>) => {};
/**
* Correct
*/
sendEvent("SIGN_OUT");
sendEvent("LOG_IN", {
userId: "123",
});
sendEvent("SIGN_UP", { username: "wan" });
/**Should error */
sendEvent("LOG_IN", {});
sendEvent("LOG_IN");
sendEvent("SIGN_UP", { errorKey: "wan" });
sendEvent("SIGN_OUT", {});
相关文章
- 记录一次在生成数据库服务器上出现The timeout period elapsed prior to completion of the operation or the server is not responding.和Exception has been thrown by the target of an invocation的解决办法
- [systemd]How To Use Systemctl to Manage Systemd Services and Units
- [Typescript] Using Generic Context to Avoid Distributivity in Conditional Types
- [Typescript] 98. Medium - Append to object
- [Typescript] Get a TypeScript package ready for release to NPM
- [Typescript] Convert a js project to typescript
- [Typescript] Making TypeScript Stick - 3
- [TypeScript] Typescript Intersection & Union Types
- [Typescript] Narrow the unknown Type with TypeScript's Assertion Functions
- [Typescript] Create Type From Any Given Data in TypeScript
- [Typescript] Improve Readability with TypeScript Numeric Separators when working with Large Numbers
- [Typescript Kaop-ts] Use AOP in Vue Components with TypeScript and Kaop-ts
- [Typescript] Generics using TypeScript
- [TypeScript] Reflection and Decorator Metadata
- The nodes should be added to the underlying vendor clusterware before adding them to the CRS cluster
- Caused by: org.xml.sax.SAXParseException: The reference to entity "characterEncoding" must end with the ';' delimiter.
- [Typescript] 136. Medium - Object to Union
- [Typescript] Map an Object to a Union of Tuples
- [Typescript] 54. Medium - Tuple to Nested Object
- [Typescript] Tips: Use 'extends' keyword to narrow the value of a generic
- [Typescript] Tips: Use 'in' operator to transform a union to another union(watched)
- [TypeScript] Typescript Intersection & Union Types
- [React Typescript 2022] Use TypeScript to Type a React Class Component
- [Typescript] Use the Nullish Coalescing Operator in TypeScript (isNil)
- [Typescript] Simplify iteration of custom data structures in TypeScript with iterators (backwards iteration with for ... of.. loop)
- [VueJS + Typescript] Decouple Dependencies Using IoC Containers in Vue with TypeScript and InversifyJS
- [TypeScript] Typescript Interfaces vs Aliases Union & Intersection Types
- [TypeScript] Using Assertion to Convert Types in TypeScript
- You currently don‘t have access to this membership resource. To resolve this issue, agree to the lat
- 成功解决To fix this you could try to: 1. loosen the range of package versions you‘ve specified
- The current user does not have write permissions to the target environment.
- 【已解决】RuntimeError: The following handlers are available to decode the pixel data however they are
- Kubernetes-kubectl The connection to the server localhost:8080 was refused -did you specify
- git push报错 fatal: The current branch master has no upstream branch. To push the current