如何强制函数参数(对象)具有特定的键模式

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

How to coerce a function argument (object) have specific key pattern

问题

我有一个案例,需要创建一个接受具有特定键的对象的函数,这些键包含特定的值。具体来说:

type ArgType = {
   name: string
   selectors: {
      [key: string]: Selector
   }
}

在这个示例中,Selector 被定义为一个 <(state: S) => unknown>

然而,我想强制这个 selectors 对象具有特定的键模式,即键应该遵循 select${Capitalize<string>} 的模式,因此当涉及到该函数的参数时,参数必须符合此模式,换句话说:

Foo( { 
   name: "Bar",
   selectors: {
      selectBuzz: () => {},
      fizz: () => {},
      selectFizz: '123',
   }
})

对象参数将报告错误,因为 "fizz" 不符合 "selectFizz" 的命名模式,同时 selectFizz 也不是一个选择器。

我该如何做到这一点?

英文:

I have a case where I need to make a function that accepts an object with specific keys, which hold specific values. Namely:

type ArgType = {
   name: string
   selectors: {
      [key: string]: Selector
   }
}

For the purpose of this example, a Selector is defined as a &lt;S&gt;(state: S) =&gt; unknown

However, I would like to coerce this selectors object to have a specific key pattern, namely the keys should follow the pattern of select${Capitalize&lt;string&gt;}, so when the function in question receives it's arguments, the argument must conform to this pattern, or in other words:

Foo( { 
   name: &quot;Bar&quot;,
   selectors: {
      selectBuzz: () =&gt; {},
      fizz: () =&gt; {},
      selectFizz: &#39;123&#39;,
   }
})

An object argument would report error for both "fizz" as it is missing the naming pattern of "selectFizz" as well as selectFizz as it is not a selector.

How would I do that?

答案1

得分: 1

自 TypeScript 4.4 起,所谓的 模式 模板字符串类型(如在 microsoft/TypeScript#40598 中实现)可以用作 索引签名 的键类型。因此,您可以这样做:

type ArgType = {
  name: string,
  selectors: {
    [key: `select${Capitalize<string>}`]: Selector
  }
}
type Selector = <S>(state: S) => unknown;
declare function Foo(a: ArgType): void;

并且它的行为如下所示:

Foo({
  name: "Bar",
  selectors: {
    selectBuzz: () => { },
    fizz: () => { },  // 直到解决下面的错误之前都不会出错
    selectFizz: '123' // 错误
  }
})

Foo({
  name: "Bar",
  selectors: {
    selectBuzz: () => { },
    fizz: () => { }, // 错误    
    selectFizz: () => { }
  }
})

Foo({
  name: "Bar",
  selectors: {
    selectBuzz: () => { },
    selectFizz: () => { }
  }
}) // 可行

Playground 链接到代码

英文:

Since TypeScript 4.4, so-called pattern template literal types (as implemented in microsoft/TypeScript#40598) can be used as the key type of an index signature. So you can do this:

type ArgType = {
  name: string,
  selectors: {
    [key: `select${Capitalize&lt;string&gt;}`]: Selector
  }
}    
type Selector = &lt;S&gt;(state: S) =&gt; unknown;    
declare function Foo(a: ArgType): void;

and it behaves as desired:

Foo({
  name: &quot;Bar&quot;,
  selectors: {
    selectBuzz: () =&gt; { },
    fizz: () =&gt; { },  // not an error until you resolve the below error
    selectFizz: &#39;123&#39; // error
  }
})

Foo({
  name: &quot;Bar&quot;,
  selectors: {
    selectBuzz: () =&gt; { },
    fizz: () =&gt; { }, // error    
    selectFizz: () =&gt; { }
  }
})

Foo({
  name: &quot;Bar&quot;,
  selectors: {
    selectBuzz: () =&gt; { },
    selectFizz: () =&gt; { }
  }
}) // okay

Playground link to code

huangapple
  • 本文由 发表于 2023年7月18日 03:18:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76707504.html
匿名

发表评论

匿名网友

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

确定