[!Typescript] Tips: dynamic specify the type of arguments to function
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", {});
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2018-10-20 [Unit Testing] Mock an HTTP request using Nock while unit testing
2015-10-20 [AngularJS] Enable Animations Explicitly For A Performance Boost In AngularJS
2015-10-20 [AngularJS + Unit Testing] Testing Directive's controller with bindToController, controllerAs and isolate scope