简体   繁体   English

在打字稿中指定 keyof 类型

[英]specify keyof type in typescript

Is there a way to specify the key that are already defined in type?有没有办法指定类型中已经定义的键?

interface KeyType {
 userName: string,
 address: string
}

type ValidationType = {
 userName: ValidateUserNameType;
 address: ValidateAddressType;
}

Those KeyType and ValidationType is being used for different things but ValidationType key will always be the same as KeyType .这些KeyTypeValidationType用于不同的事情,但ValidationType键将始终与KeyType相同。

I've been looking around but I got no luck我一直在环顾四周,但我没有运气

My proposition here is to create third type which will join these two in the way you want.我在这里的提议是创建第三种类型,它将以您想要的方式加入这两种类型。 Consider:考虑:


interface KeyType {
    userName: string,
    address: string
}
type ValidationRules = {
    userName: ValidateUserNameType;
    address: ValidateAddressType;
    other: ValidateUserNameType; // this field will not be in ValidationType
}
// Validation type below is not affected by any additional key in ValidationRules
// keys are applied only if are added in KeyType and in ValidationRules
type ValidationType = {
    [K in keyof KeyType]: ValidationRules[K]
}

After that our type ValidationType will always have:之后,我们的类型ValidationType将始终具有:

  • keys from KeyType KeyType
  • will have an error if there is no rule in ValidationType for a key in KeyType如果ValidationType没有针对KeyType的键的规则,则会出现错误
  • will skip any additional keys from ValidationRules将跳过ValidationRules任何其他键

In other words ValidationType is fully driven by both types, and will have only keys existing in both, any key which not exists in both will be skipped or be an compile error.换句话说, ValidationType完全由两种类型驱动,并且只有键存在于两者中,任何不存在于两者中的键将被跳过或编译错误。

You could define a custom type that enforces same keys:您可以定义强制执行相同键的自定义类型:

type SameKeys<T, U extends Record<keyof T, any>> =
    { [K in keyof U]: K extends keyof T ? U[K] : never }

// e.g.
type SameKeysValidationType = SameKeys<KeyType, ValidationType>

U must extend all keys from T . U必须从T扩展所有键。 If U has more properties, they will be resolved to never value type.如果U有更多属性,它们将被解析为never不值类型。 But this won't throw a compile error yet - two options here:但这不会引发编译错误 - 这里有两个选项:

interface extension接口扩展

interface ValidationType extends SameKeys<KeyType, ValidationType> {
    userName: ValidateUserNameType;
    address: ValidateAddressType;   // comment => compile error
    // foo: string                  // uncomment => compile error
}

Assertion type断言类型

// generic assert type
type AssertSameKeys<T, U extends Record<keyof T, any> & SameKeys<T, U>> = true

// this will error, when ValidationType is not proper
type AssertValidationType = AssertSameKeys<KeyType, ValidationType> 

Above variants will work with your case.以上变体适用于您的情况。 You should still evaluate and test, what you want to do with optional properties and other edge cases.你仍然应该评估和测试你想用可选属性和其他边缘情况做什么。 Hope it helps!希望能帮助到你!

Playground sample here 游乐场示例在这里

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM