在没有`as const`的情况下推断函数参数的字符串文字类型

问题描述 投票:0回答:2

我有一个组件,它接受一组

keys
,然后将其中一个
keys
传递给
children
渲染道具。

type PagerKeys = Readonly<[string, string, ...string[]]>; // needs to be at least 2 items

interface PagerProps<Keys extends PagerKeys> {
    children: (
        props: {
            currentKey: Keys[number]
        }
    ) => ReactNode;
    keys: Keys;
}

function Pager<Keys extends PagerKeys>({
    children, keys
}: PagerProps<Keys>) {
    const [currentKey, setCurrentKey] = useState<Keys[number]>(keys[0]);

    return children({
        currentKey
    });
}

我可以通过将

currentKey
添加到
keys
属性来输入检查渲染属性中的
as const
是否与
keys
匹配。 (因为这个原因,上面的
PagerKeys
Readonly
)。

<Pager keys={['a', 'b'] as const}>
    {({currentKey}) => {
        if (currentKey === 'a') {}
        if (currentKey === 'lalala') {} // throws error as it should because 'lalala' is not a key
        ...
    }}
</Pager>

我想知道是否有一种方法可以在不添加

keys
的情况下推断
as const
中的字符串文字?

reactjs typescript
2个回答
4
投票

TypeScript 5.0 引入了

const
类型参数,让您可以向类型参数添加
const
修饰符,以向编译器询问与使用
const
断言
时得到的相同类型的推断。 这使得generic函数实现者可以轻松地要求类似
as const
的行为,而不必使用更晦涩的技巧(例如microsoft/TypeScript#30680中描述的技巧)。

就您而言,更改就像

一样简单
function Pager<const K extends PagerKeys>({
    // ------> ^^^^^
    children, keys
}: PagerProps<K>) {
    const [currentKey, setCurrentKey] = useState<K[number]>(keys[0]);

    return children({
        currentKey
    });
}

现在当你打电话时

<Pager keys={['a', 'b']}>
    {({ currentKey }) => {
        if (currentKey === 'a') { }
        if (currentKey === 'lalala') { } // throws error as it should because 'lalala' is not a key
        return null!
    }}
</Pager>

编译器根据需要将类型参数推断为

readonly ["a", "b"]

// (property) PagerProps<readonly ["a", "b"]>.keys: readonly ["a", "b"]

Playground 代码链接


1
投票

5.0 之前,仍然可以使用 可变元组类型 将字符串推断为文字类型:

interface PagerProps<Keys extends PagerKeys> {
    children: (props: { currentKey: Keys[number] }) => any;
    keys: [...Keys]; // ✨
}

这是唯一需要的改变!

游乐场

© www.soinside.com 2019 - 2024. All rights reserved.