简体   繁体   English

如何表达通用约束以具有特定类型的动态属性

[英]How to express a generic constraint to have a dynamic property of a specific type

I'm building a library that provide a generic utility function.我正在构建一个提供通用实用程序 function 的库。

This function should do something with one of the property of the incoming object, but the property name is also a parameter provided by the user.这个 function 应该对传入的 object 的属性之一做一些事情,但属性名称也是用户提供的参数。

To simplify, imagine:为了简化,想象一下:

type T1 = {
    id: string;
    foo: number;
    bar: string[];
}
const sampleData1: T1 = { bar: ["a"], foo: 42, id: "myid" }
const doSomething = <F>(somearg: F, path: keyof F) => {
    console.log(somearg[path]);
}

doSomething(sampleData1, "id");

The output is what I expect: "myid" . output 是我所期望的: "myid"

However, I want only string to be used in my function.但是,我只想在我的 function 中使用字符串。 But the actual code will also work with:但实际代码也适用于:

type T3 = {
    wrong: number;
    value: number;
}
const sampleData3 : T3 = { value : 100, wrong : 5 }

const doSomething = <F>(somearg: F, path: keyof F) => {
    console.log(somearg[path]);
}

doSomething(sampleData3, "wrong");

This code works and emits 5 .此代码有效并发出5 But my actual function should only works with strings.但我实际的 function 应该只适用于字符串。

Is there a way to express the F generic type to have the dynamically name property be only a string?有没有办法表达F泛型类型以使动态名称属性只是一个字符串?

I tried:我试过了:

const doSomething = <F extends { [path] : string }>(somearg: F, path: keyof F) => {

    console.log(somearg[path]);

}

but the syntax is invalid:但语法无效:

A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.
Cannot find name 'path'.

How to fix that?如何解决?

FYI: I run TS 4.5.5.仅供参考:我运行 TS 4.5.5。 My actual function is in a dependency, and the consuming code is present in multiple apps, with very different business needs.我实际的 function 处于依赖关系中,并且消费代码存在于多个应用程序中,具有非常不同的业务需求。

The utility function may also be called several times on the same object, but with different property name.实用程序 function 也可以在同一个 object 上调用多次,但属性名称不同。

Full repro on TS playground TS 操场上的完整复制

The syntax to index an object type in this case is { [key in KeyType]: valueType } .在这种情况下,索引 object 类型的语法是{ [key in KeyType]: valueType }

In your case, you want to constrain F so that the path has a string value, but you do not care about the rest.在您的情况下,您希望约束F以使路径具有字符串值,但您不关心 rest。

You can use 2 generic types: 1 for the path, and 1 for the object:您可以使用 2 种通用类型:1 用于路径,1 用于 object:

const doSomething = <P extends string, F extends { [p in P]: string }>(somearg: F, path: P) => {}

It correctly rejects the 3rd sample:它正确拒绝了第三个样本:

doSomething(sampleData1, "id");
doSomething(sampleData2, "key");
doSomething(sampleData3, "wrong"); // Error: Type 'number' is not assignable to type 'string'.

Playground Link 游乐场链接

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

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