如何向打字稿解释该变量始终是泛型类中的字符串

Fut*_*ake 5 generics types typescript

我有以下类和接口定义:

import { Component } from 'react';

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

interface SearchListProps<T extends object, K extends KeysMatching<T, string>> {
    data: T[];
    sort_and_filter_key: K;
}

class SearchList<ItemDataT extends object, K extends KeysMatching<ItemDataT, string>> extends Component<SearchListProps<ItemDataT, K>> {

    constructor(props: SearchListProps<ItemDataT, K>) {
        super(props);

        const value = props.data[0][props.sort_and_filter_key]; // ItemDataT[K] -> should be string
    }
}

// exmple case: 

interface DataExample {
    name: string, 
    city: string,
    id: number,
    content: object
    // etc
}

const example_data: DataExample[] = [
    {
        name: "asd",
        city: "bcn",
        id: 1,
        content: {}
    },
    {
        name: "dkg",
        city: "nld",
        id: 2,
        content: {}
    }
];

<SearchList data={example_data} sort_and_filter_key={"city"}></SearchList>
Run Code Online (Sandbox Code Playgroud)

正如您在代码中所注释的那样,打字稿认为 value 是类型,ItemDataT[K]但它应该是string。

为什么?因为该属性sort_and_filter_key应该只允许其值为字符串的键,因为以下通用表达式:K extends KeysMatching<T, string>。但打字稿似乎不明白这一点。

自动完成似乎确实可以理解,请参见下图:
在此输入图像描述
由于这张图clear只允许保证是字符串的两个key。

我如何让 tsc 也理解这一点?
如果有任何不清楚的地方,请告诉我,以便我修改问题。

art*_*iak 0

问题似乎是Typescript 推理能力对于泛型类型的限制 - Typescript 不会跟踪所有可推理的约束。这样做肯定需要一些权衡。

对于具体类型,推理按预期进行:

const props: SearchListProps<DataExample> = {
  data: example_data,
  sort_and_filter_key: 'city', 
};

const ok_string = props.data[0][props.sort_and_filter_key];
Run Code Online (Sandbox Code Playgroud)

如果是泛型类型,我们需要手动向 TS 引擎给出我们到底感兴趣的提示:

interface SearchListProps<T> {
  data: (T &  Record<KeysMatching<T, string>, string>)[];
  sort_and_filter_key: KeysMatching<T, string>;
}
Run Code Online (Sandbox Code Playgroud)

有趣的是,我们可以T与其他任何东西相交 - 例如Record<KeysMatching<T, string>, number>,但是我们无法SearchListProps使用具体类型进行初始化。

固定和简化版本: https://stackblitz.com/edit/react-ts-x4jdez

顺便提一句。props.data[0][props.sort_and_filter_key]不安全(noUncheckedIndexedAccess ]。