从具有布尔类型属性的对象构建类型?

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

Building a Type from an object with properties of type Boolean?

问题

我想从这个对象构造一个类型:

const isSynchronized: Record<SynchronizableField, boolean> = {
    /* synchronized */
    surveyMacroEnvironments: true,
    coordinateReferenceSystemCrs: true,
    transactionType: true,
    epsgTransformation: true,
    startingAgreementDate: true,
    expirationAgreementDate: true,
    transactionTypeNotes: true,
    surveyDataType: true,
    /* not synchronized */
    surveyName: false,
    validationStateCd: false,
    legacy: false,
    notifyOnCreate: false,
    notifyOnValidate: false,
    finalReportLink: false,
    // timestamp fields
    creationDate: false,
    lastUpdate: false,
    // continent and country are handled differently
    continent: false,
    country: false,
};

类型需要只包含值为true的键,请问您能帮我或提供任何建议吗?

谢谢

英文:

I would like to construct a type from this object:

const isSynchronized: Record&lt;SynchronizableField, boolean&gt; = {
    /* synchronized */
    surveyMacroEnvironments: true,
    coordinateReferenceSystemCrs: true,
    transactionType: true,
    epsgTransformation: true,
    startingAgreementDate: true,
    expirationAgreementDate: true,
    transactionTypeNotes: true,
    surveyDataType: true,
    /* not synchronized */
    surveyName: false,
    validationStateCd: false,
    legacy: false,
    notifyOnCreate: false,
    notifyOnValidate: false,
    finalReportLink: false,
    // timestamp fields
    creationDate: false,
    lastUpdate: false,
    // continent and country are handled differently
    continent: false,
    country: false,
};

where the type needs to have only the keys with values equal to true, could you please help me or give me any suggestions?

Thanks

答案1

得分: 1

作为第一步,我们需要删除isSynchronized上的type annotation; 我们需要编译器 推断 其类型,然后使用推断的类型来计算你正在寻找的键集。您可以使用the satisfies operator来确保属性类型被检查并限制为boolean

const isSynchronized = {
    surveyMacroEnvironments: true,
    coordinateReferenceSystemCrs: true,
    transactionType: true,
    epsgTransformation: true,
    startingAgreementDate: true,
    // ✂ ⋯ ✂
    lastUpdate: false,
    continent: false,
    country: false,
} satisfies Record<string, boolean>;

type IsSynchronized = typeof isSynchronized;

现在,您可以检查IsSynchronized以获取所需的类型。

您正在寻找应用我称之为 KeysMatching<T, V> 的类型函数,如microsoft/TypeScript#48992 中所请求的,以及在https://stackoverflow.com/q/54520676/2887218 中讨论的。其思想是 KeysMatching<T, V> 将计算为T的属性键的union,其中这些键的属性值可分配给V。具体来说,看起来您想要的是 KeysMatching<IsSynchronized, true>

语言本身没有提供本机的 KeysMatching,但有多种方法可以自己实现它,具有各种问题和边缘情况。一种方法是使用分布式对象类型,我们可以遍历T的所有属性,然后索引到结果中的所有键,以得到计算的属性类型的union。就像这样:

type KeysMatching<T, V> =
    { [K in keyof T]: T[K] extends V ? K : never }[keyof T]

然后让我们使用它:

type SynchronizedKeys = KeysMatching<IsSynchronized, true>;
// type SynchronizedKeys = "surveyMacroEnvironments" | "coordinateReferenceSystemCrs" |
//   "transactionType" | "epsgTransformation" | "startingAgreementDate" | 
//   "expirationAgreementDate" | "transactionTypeNotes" | "surveyDataType"

看起来不错。如果您不想保留 KeysMatching,您可以内联定义以直接计算SynchronizedKeys

type SynchronizedKeys = {
    [K in keyof IsSynchronized]: IsSynchronized[K] extends true ? K : never
}[keyof IsSynchronized];

Playground link to code

英文:

As a first step we have to remove that type annotation on isSynchronized; we need the compiler to infer its type and then use that inferred type to compute the key set you're looking for. You could use the satisfies operator instead to make sure the property types are checked against and constrained to boolean:

const isSynchronized = {
    surveyMacroEnvironments: true,
    coordinateReferenceSystemCrs: true,
    transactionType: true,
    epsgTransformation: true,
    startingAgreementDate: true,
    // ✂ ⋯ ✂
    lastUpdate: false,
    continent: false,
    country: false,
} satisfies Record&lt;string, boolean&gt;;

type IsSynchronized = typeof isSynchronized;

Now you can inspect IsSynchronized to get the desired type.


You're looking for an application of a type function I call KeysMatching&lt;T, V&gt;, as requested in microsoft/TypeScript#48992 and as discussed in
https://stackoverflow.com/q/54520676/2887218. The idea is that KeysMatching&lt;T, V&gt; would evaluate to the union of property keys of T where the property values at those keys are assignable to V. Specifically it looks like you want KeysMatching&lt;IsSynchronized, true&gt;.

There's no native KeysMatching provided by the language, but there are a number of ways to implement it yourself, with various issues and edge cases. One approach is a distributive object type where we map over all the properties of T and then index into the result with all the keys to end up with the union of the computed property types. Like this:

type KeysMatching&lt;T, V&gt; =
    { [K in keyof T]: T[K] extends V ? K : never }[keyof T]

And let's use it:

type SynchronizedKeys = KeysMatching&lt;IsSynchronized, true&gt;;
// type SynchronizedKeys = &quot;surveyMacroEnvironments&quot; | &quot;coordinateReferenceSystemCrs&quot; |
//   &quot;transactionType&quot; | &quot;epsgTransformation&quot; | &quot;startingAgreementDate&quot; | 
//   &quot;expirationAgreementDate&quot; | &quot;transactionTypeNotes&quot; | &quot;surveyDataType&quot;

Looks good. If you don't want to keep KeysMatching around, you can inline the definition to compute SynchronizedKeys directly:

type SynchronizedKeys = {
    [K in keyof IsSynchronized]: IsSynchronized[K] extends true ? K : never
}[keyof IsSynchronized];

Playground link to code

huangapple
  • 本文由 发表于 2023年6月1日 22:33:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76383009.html
匿名

发表评论

匿名网友

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

确定