TypeScript如何根据输入参数定义字面量类型实现createContext?
问题:实现动态键名的createContext函数并让TypeScript正确识别
我想实现一个createContext函数,返回对象的键名基于输入参数的名称前缀,希望TypeScript能识别返回值的键由输入参数决定。尝试了以下代码:
export function createContext<Name extends string = string>( name: Name, ): { [`use${name}Context`]: any; [`${name}Provider`]: any; }; export function createContext(name:string){ return { [`use${name}Context`]:0, [`${name}Provider`]:0 } }
但遇到了错误:
A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.(1170)
想问这是不是意味着没法实现需求?
错误原因
TypeScript禁止在类型字面量中使用泛型变量作为计算属性名,因为你定义的Name是string的子类型,但不属于字面量类型或unique symbol类型,不符合类型字面量对计算属性名的要求。
解决方案
使用映射类型结合Template Literal Types来生成动态键名,就能绕过这个限制:
export function createContext<Name extends string>( name: Name, ): { [K in `use${Name}Context` | `${Name}Provider`]: any; }; export function createContext(name: string) { return { [`use${name}Context`]: 0, [`${name}Provider`]: 0, }; }
修改后,当你传入具体的字面量参数(比如createContext('Auth')),TypeScript会自动推断返回类型为{ useAuthContext: any; AuthProvider: any; },完全符合需求。
可选优化:泛型化上下文值
如果需要更精准的类型,可以给上下文值添加泛型,让返回的Hook和Provider类型更贴合实际场景:
import React from 'react'; export function createContext<Name extends string, T = unknown>( name: Name, defaultValue?: T, ): { [K in `use${Name}Context`]: () => T; } & { [K in `${Name}Provider`]: React.Provider<T>; }; export function createContext(name: string, defaultValue?: unknown) { const context = React.createContext(defaultValue); return { [`use${name}Context`]: () => React.useContext(context), [`${name}Provider`]: context.Provider, }; }
内容的提问来源于stack exchange,提问作者wener
相关产品推荐
相关产品推荐

