javascript 在接口中使用Typescript中常量的名称创建函数

whhtz7ly  于 2023-03-11  发布在  Java
关注(0)|答案(2)|浏览(95)

是否可以使用const中的名称在接口中创建函数?我有const,其中包含所有事件名称,我想为SocketIO创建ServerToClientEvents接口。
我可以写这样的东西,它会工作

interface A {
    "funcName": () => void
}

但是我可以在这个接口中创建名称来自FunNames的函数吗?

export const Events = {
    user_updated: "user:updated",
    empty: "empty"
}

interface ServerToClientEvents {
    Events.empty: () => void;
    Events.user_updated: (user: User) => void;
}
mwg9r5ms

mwg9r5ms1#

你可以用一个mapped type和一个嵌套的conditional type来测试我们Map的键,看看它是否匹配一个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) {},
};

Playground链接
我假设user_前缀应该表示函数接受User对象,给出问题中显示的代码,但是当然您可以根据需要进行调整。
使用给定的Events常量,该Map类型定义了以下结构:

{
    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>;
};

Playground链接

u5rb5r59

u5rb5r592#

如果Events不是动态的,也许constAssert可以完成这项工作。

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;
}

相关问题