在Typescript中,使用常量创建接口中的函数。

huangapple go评论77阅读模式
英文:

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

Playground链接

在那里,我假设user_前缀应该表示函数接受一个User对象,根据问题中显示的代码,但你当然可以根据需要进行调整。

使用给定的Events常量,该映射类型定义了这个结构:

{
    user_updated: (user: User) => void;
    empty: () => void;
}

在Typescript中,使用常量创建接口中的函数。

为了提高可读性,你可以拆分条件类型:

type ServerFunctionType<Key extends string> =
    Key extends `user_${string}`
        ? (user: User) => void
        : () => void;

type ServerToClientEvents = {
    [Key in keyof typeof Events]: ServerFunctionType<Key>;
};

Playground链接

英文:

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: &quot;user:updated&quot;,
    empty: &quot;empty&quot;,
};

type ServerToClientEvents = {
    [Key in keyof typeof Events]: Key extends `user_${string}` ? (user: User) =&gt; void : () =&gt; void;
};

const goodExample: ServerToClientEvents = {
    user_updated(user: User) {},
    empty() {},
};

const badExample: ServerToClientEvents = {
    //^^^^^^^^^^^−−−−− Property &#39;empty&#39; is missing in type &#39;{ user_updated(user: User): void; }&#39; but required in type &#39;ServerToClientEvents&#39;.ts(2741)
    user_updated(user: User) {},
};

Playground link

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) =&gt; void;
    empty: () =&gt; void;
}

在Typescript中,使用常量创建接口中的函数。

For readability, you might split out the conditional type:

type ServerFunctionType&lt;Key extends string&gt; =
    Key extends `user_${string}`
        ? (user: User) =&gt; void
        : () =&gt; void;

type ServerToClientEvents = {
    [Key in keyof typeof Events]: ServerFunctionType&lt;Key&gt;;
};

Playground link

huangapple
  • 本文由 发表于 2023年3月9日 19:02:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/75683702.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定