在 TypeScript 中通过动态键-函数映射确保类型安全
我正在使用 TypeScript,并且在动态将键映射到特定处理函数时遇到了确保类型安全的挑战。下面是说明我问题的 TypeScript 代码片段:
interface Foo {
foo: string
}
interface Bar {
bar: string
}
const fooProcessor = (foo: Foo) => {
return foo
}
const barProcessor = (bar: Bar) => {
return bar
}
const processorMap = {
foo: fooProcessor,
bar: barProcessor,
}
const fooGenerator = () => ({ foo: '123' } as Foo)
const barGenerator = () => ({ bar: '123' } as Bar)
const generatorMap = {
foo: fooGenerator,
bar: barGenerator,
}
const topLevelProcessor = (type: 'foo' | 'bar') => {
const object = generatorMap[type]()
return processorMap[type](object)
}
挑战出现在 topLevelProcessor 函数中,TypeScript 无法推断对象和函数 processorMap[type] 的正确类型。这导致类型不匹配错误。我正在尝试避免使用 as any,以保持强类型安全。
答案#1
在字符串字面量和类型之间建立绑定的最直接方法是创建辅助接口(下文的KnownTypeBinding):
interface Foo {
foo: string;
}
interface Bar {
bar: string;
}
interface KnownTypeBinding {
foo: Foo;
bar: Bar;
}
type KnownTypeName = keyof KnownTypeBinding;
type KnownType = KnownTypeBinding[KnownTypeName];
type TypeProcessor<T extends KnownType> = (x: T) => T;
type TypeGenerator<T extends KnownType> = () => T;
type ProcessorMap = {
[K in KnownTypeName]: TypeProcessor<KnownTypeBinding[K]>;
}
const processorMap: ProcessorMap = {
foo: (foo: Foo) => { return foo; },
bar: (bar: Bar) => { return bar; }
}
type GeneratorMap = {
[K in KnownTypeName]: TypeGenerator<KnownTypeBinding[K]>;
}
const generatorMap: GeneratorMap = {
foo: () => { return { foo: 'foo' }; },
bar: () => { return { bar: 'bar' }; }
}
type TopLevelProcessor = <K extends KnownTypeName>(type: K) => KnownTypeBinding[K];
const topLevelProcessor: TopLevelProcessor = <K extends KnownTypeName>(type: K) => {
const object = generatorMap[type]()
return processorMap[type](object);
}
