繁体   English   中英

如何在 TypeScript 中使用模板文字类型作为返回类型属性

[英]How to use Template Literal Types as a return type property in TypeScript

我正在尝试TypeScript 4.1版本中的新模板文字类型功能,并希望创建 function 接受字符串文字参数,然后使用该参数声明返回类型 ZA8CFDE6331BD59EB26AC96B 的属性。

作为一个实验,我试图围绕 React 的useState function 创建一个小包装器,但无法让它工作。

这是我尝试过的:

function useNamedState<TValue>(name: string, initialValue: TValue): {
    [typeof name]: TValue;
    [`set${Capitalize<typeof name>}`]: (newValue: TValue) => void;
} {
    const [value, setValue] = useState(initialValue);

    return {
        [name]: value,
        [`set${capitalize(name)}`]: newValue => setValue(newValue),
    };
}

我不确定这里应该使用什么正确的语法。 我想实现如下API:

const {apples, setApples} = useNamedState<number|null>('apples', null);

我怎样才能让它工作?

您需要一个额外的类型来捕获name参数的实际字符串文字类型。 您还需要使用映射类型或预定义的Record映射类型来创建具有来自字符串文字类型的键的类型。

一个复杂的问题是 TS 不支持部分参数推断,因此对于如何定义 function,您有几个选择。

  1. 单个 function 具有显式类型 arguments 或推断类型但具有类型断言:

function useNamedState<TValue, TName extends string>(name: TName, initialValue: TValue): Record<TName, TValue> & Record<`set${Capitalize<typeof name>}`, (newValue: TValue) => void>
{ /*...*/ }

const {apples, setApples} = useNamedState<number|null, 'apples'>('apples', null); // explicit args 
const {bannana, setBannana} = useNamedState('bannana', null as null | number); // implicit args,but with type assertion on value  

游乐场链接

  1. 用 function 柯里化。 具有相同顺序的参数(但笨重的类型参数列表)
function useNamedState <TName extends string>(name: TName)
{
    return function  <TValue>(initialValue: TValue): Record<TName, TValue> & Record<`set${Capitalize<typeof name>}`, (newValue: TValue) => void> {
        // ....
    }
}
// TValue specified in the middle is hard to read
const {apples, setApples} = useNamedState('apples')<number|null>(null);

游乐场链接

  1. 用 function 柯里化。 以相反的顺序使用参数(但可以输入参数列表)
function useNamedState <TValue>(initialValue: TValue)
{
    return function <TName extends string>(name: TName): Record<TName, TValue> & Record<`set${Capitalize<typeof name>}`, (newValue: TValue) => void> {
         //....
    }
}

const {apples, setApples} = useNamedState<number|null>(null)('apples');

游乐场链接

暂无
暂无

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

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