简体   繁体   English

如何限制 TypeScript 方法接收特定类型字段的“keyof”值?

[英]How can I restrict a TypeScript method to receive `keyof` values for fields of a certain type?

I am trying to write a function that will update a field of an object if a value that was passed in changed versus what's already in the object. The closest thing i've got so far is我正在尝试编写一个 function,如果传入的值与 object 中已有的值发生变化,它将更新 object 的字段。到目前为止,我最接近的是

type KnownCountryKeys = "defaultCountry" | "country";
type IHasCountry = {
  [key in KnownCountryKeys]: Country;
};

export async function maybeUpdateCountry<THasCountry extends IHasCountry>(
  dto: THasCountry,
  countryKey: KnownCountryKeys,
  newCountryCode: string
) {
  // Pseudo-Code

  // Ideally, typescript could validate at build-time that
  // `dto[countryKey]` is in-fact a Country field, from
  // the type annotations alone.
  if (dto[countryKey].code != newCountryCode) {
    const newCountry = //...validateCountry
    dto[countryCode] = newCountry;
  }
}

My main problem with this approach is that dto can not have any more fields other than the ones specified in KnownCountryKeys I get ts2345 , but if I try to convert it to an interface to make the type flexible I get ts2464 .这种方法的主要问题是dto不能有除KnownCountryKeys中指定的字段之外的任何其他字段,我得到ts2345 ,但是如果我尝试将它转换为接口以使类型灵活,我得到ts2464 Furthermore, I'd like to delete KnownCountryKeys because having that whitelist of field names is a code-smell.此外,我想删除KnownCountryKeys ,因为拥有该字段名称白名单是一种代码味道。

My intent is for this function to receive an arbitrary object of any shape, a string key that is validated by TypeScript to be a field of type Country , and the key of the new country so I can decided whether the country must be updated in an entirely type-safe fashion.我的目的是让这个 function 接收任意形状的任意 object,一个由 TypeScript 验证为Country类型字段的字符串键,以及新国家的键,这样我就可以决定是否必须更新国家完全类型安全的时尚。

If I understood You properly, You look for something like:如果我对你的理解正确,你会寻找类似的东西:

type IHasCountry<K extends KnownCountryKeys> = { [key in K]: Country; };

export function maybeUpdateCountry<K extends KnownCountryKeys>(
    dto: IHasCountry<K>, countryKey: K, newCountryCode: string) {
// ...

EDIT:编辑:

If you assume that country code is arbitrary string but the DTO should have a field named as country code with type Country, then:如果您假设国家代码是任意字符串,但 DTO 应该有一个名为国家代码且类型为 Country 的字段,那么:

class Country { constructor(readonly name: string) { } };

function maybeUpdateCountry<K extends string, T extends { [key in K]: Country }>(
  dto: T, countryKey: K, newCountryCode: string): void {}


const dto1 = { 'pl_PL': new Country('Poland') };
const dto2 = { 'fr_CH': new Country('Switzerland') };
const dto3 = { 'fr_FR': new Country('France') };


maybeUpdateCountry(dto1, 'pl_PL', 'Pologne'); // OK
maybeUpdateCountry(dto2, 'fr_CH', 'Suisse'); // OK

maybeUpdateCountry(dto2, 'fr_FR', 'Suisse'); 
// ERROR: 
// Argument of type '{ fr_CH: Country; }' is not assignable to parameter of type '{ fr_FR: Country; }'.
//  Property 'fr_FR' is missing in type '{ fr_CH: Country; }' but required in type '{ fr_FR: Country; }'.


maybeUpdateCountry(dto2, 'test', 'Test'); 
// ERROR: 
// Argument of type '{ fr_CH: Country; }' is not assignable to parameter of type '{ test: Country; }'.
//  Property 'test' is missing in type '{ fr_CH: Country; }' but required in type '{ test: Country; }'.

maybeUpdateCountry({ hello: 'bonjour' }, 'test', 'Test');
// ERROR:
// Argument of type '{ hello: string; }' is not assignable to parameter of type '{ test: Country; }'.
//  Object literal may only specify known properties, and 'hello' does not exist in type '{ test: Country; }'.

maybeUpdateCountry({ test: 'Not a country' }, 'test', 'Test');
// ERROR:
// Type 'string' is not assignable to type 'Country'

maybeUpdateCountry({ test: new Country('Testland') }, 'test', 'Test'); // OK

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 TypeScript:限制keyof类型 - TypeScript: Restrict keyof type Typescript 某类密钥 - Typescript keyof of a certain type TypeScript 可以将 keyof 限制为特定类型的属性列表吗? - can TypeScript restrict keyof to a list of properties of a particular type? 如何获取 Typescript 中 keyof 变量的类型? - How can I get the type of a keyof variable in Typescript? 为什么不能在类型定义中使用某些字段和keyof - Why can't use certain fields and keyof in a type definition 如何使用 `react-hook-form` 将 `TFieldName` 限制为特定类型的字段? - How can I restrict `TFieldName` to fields of a certain type with `react-hook-form`? TypeScript数组类型转换与keyof like方法 - TypeScript array type transform with keyof like method 如何将方法的泛型限制为typescript中的object? - How to restrict a generic type of a method to an object in typescript? 有没有办法输入 TypeScript 方法装饰器来限制它可以装饰的方法的类型? - Is there a way to type a TypeScript method decorator to restrict the type of the method it can decorate? 在 TypeScript 中,如何推断我的参数并强加约束,即所有项都是 T 的键,其中 T 是函数的泛型类型? - In TypeScript, how can I infer my arguments and impose a constraint that all items be keyof T, where T is the generic type for the function?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM