英文:
Create function in interface with name from const in Typescript
问题
export const Events = {
user_updated: "user:updated",
empty: "empty"
}
interface ServerToClientEvents {
[Events.empty]: () => void;
[Events.user_updated]: (user: User) => void;
}
英文:
Is it possible to create function in interface with name from const? I have const where I have all event names and I want to create ServerToClientEvents
interface for SocketIO.
I can write something like this and it will work
interface A {
"funcName": () => void
}
But can I create functions in this interface with names from FunNames
?
export const Events = {
user_updated: "user:updated",
empty: "empty"
}
interface ServerToClientEvents {
Events.empty: () => void;
Events.user_updated: (user: User) => void;
}
答案1
得分: 2
如果Events
不是动态的,也许const断言可以胜任任务。
export const Events = {
user_updated: 'user:updated',
empty: 'empty',
} as const; //const断言
interface User {
id: string;
}
interface ServerToClientEvents {
[Events.empty]: () => void;
[Events.user_updated]: (user: User) => void;
}
英文:
If Events
isn't dynamic, maybe const assertion can do the job.
export const Events = {
user_updated: 'user:updated',
empty: 'empty',
} as const; //const assertion
interface User {
id: string;
}
interface ServerToClientEvents {
[Events.empty]: () => void;
[Events.user_updated]: (user: User) => void;
}
答案2
得分: 1
你可以使用一个mapped type和一个嵌套的conditional type,测试我们映射的键是否与template literal type匹配(这样我们可以检测是否需要user
参数):
export const Events = {
user_updated: "user:updated",
empty: "empty",
};
type ServerToClientEvents = {
[Key in keyof typeof Events]: Key extends `user_${string}` ? (user: User) => void : () => void;
};
const goodExample: ServerToClientEvents = {
user_updated(user: User) {},
empty() {},
};
const badExample: ServerToClientEvents = {
//^^^^^^^^^^^−−−−− Property 'empty' is missing in type '{ user_updated(user: User): void; }' but required in type 'ServerToClientEvents'.ts(2741)
user_updated(user: User) {},
};
在那里,我假设user_
前缀应该表示函数接受一个User
对象,根据问题中显示的代码,但你当然可以根据需要进行调整。
使用给定的Events
常量,该映射类型定义了这个结构:
{
user_updated: (user: User) => void;
empty: () => void;
}
为了提高可读性,你可以拆分条件类型:
type ServerFunctionType<Key extends string> =
Key extends `user_${string}`
? (user: User) => void
: () => void;
type ServerToClientEvents = {
[Key in keyof typeof Events]: ServerFunctionType<Key>;
};
英文:
You can do it with a mapped type and a nested conditional type testing the key we're mapping to see if it matches a template literal type (so we detect whether we need the user
parameter):
export const Events = {
user_updated: "user:updated",
empty: "empty",
};
type ServerToClientEvents = {
[Key in keyof typeof Events]: Key extends `user_${string}` ? (user: User) => void : () => void;
};
const goodExample: ServerToClientEvents = {
user_updated(user: User) {},
empty() {},
};
const badExample: ServerToClientEvents = {
//^^^^^^^^^^^−−−−− Property 'empty' is missing in type '{ user_updated(user: User): void; }' but required in type 'ServerToClientEvents'.ts(2741)
user_updated(user: User) {},
};
I've assumed there that the user_
prefix should mean the function accepts a User
object, given the code shown in the question, but of course you can tweak that as necessary.
With the given Events
constant, that mapped typ defines this structure:
{
user_updated: (user: User) => void;
empty: () => void;
}
For readability, you might split out the conditional type:
type ServerFunctionType<Key extends string> =
Key extends `user_${string}`
? (user: User) => void
: () => void;
type ServerToClientEvents = {
[Key in keyof typeof Events]: ServerFunctionType<Key>;
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论