如果我想映射所有值都是基元的对象值,这非常简单:
type ObjectOf<T> = { [k: string]: T };
type MapObj<Obj extends ObjectOf<any>> = {
[K in keyof Obj]: Obj[K] extends string ? Obj[K] : 'not string';
};
type Foo = MapObj<{
a: 'string',
b: 123,
}>; // Foo is { a: 'string', b: 'not string' }
但是,当我将联合作为对象值时,TS 不会按预期工作:type AllPaths = '/user' | '/post';
type Props<Path extends AllPaths> = MapObj<{
path: Path,
}>;
function Fn<Path extends AllPaths>({ path }: Props<Path>) {
const path2: AllPaths = path;
}
我收到错误:Type 'Path extends string ? Path : "not string"' is not assignable to type 'AllPaths'.
Type 'Path | "not string"' is not assignable to type 'AllPaths'.
Type '"not string"' is not assignable to type 'AllPaths'.
Type 'Path extends string ? Path : "not string"' is not assignable to type '"/post"'.
Type 'Path | "not string"' is not assignable to type '"/post"'.
Type 'string & Path' is not assignable to type '"/post"'.
由于联合的每个成员都是字符串,我预计 MapObj
的输出保持字符串的联合。我怎样才能解决这个问题?TS游乐场:https://www.typescriptlang.org/play?#code/C4TwDgpgBA8gRgKwgY2DAZgHgCoD4oC8UA3lANoDWAXFAM7ABOAlgHYDmAujdlAL4DcAKEGhIUALIBDMPASZZUCAA9gEFgBNasRCjRZJLELnxFigqOQDSUVlAoQQAe3TaEXV2UsdFKtZrqMrGxQAPweXlA0AOQsjsABzOxRQgLCotAAggA2WQAKksAAFlpEUQD0AK60EAxRUAA+UOVgjvTJaeDQuQyOYLSY+UU+qhpa2XkFxSYS0rKYZhZgkzSDhQA0gry4QoLoFSyoTI4sUABiLAOTw35jOau0uAAUpEtDvCs9fZdFuACUJOYoMhjvQoK9CgAmGjje6EMGTFKCIA
最佳答案
我认为问题是即使你声明 type Props<Path extends AllPaths> = MapObj<{ path: Path, }>;
像这样,它将只包含值 '/user' | '/post'
,但这种知识可能无法被 typescript 静态类型检查识别,因为它的类型是 MapObj<{ path: Path, }>
这只是一个 js 对象的 MapObj。
所以只需使用 as Path
妥协
function Fn<Path extends AllPaths>({ path }: Props<Path>) {
const path2: AllPaths = path as Path;
}
或者像这样为 PathObj 声明一个类型:type AllPaths = '/user' | '/post';
type AllPathObj = {
path: AllPaths,
}
type Props<PathObj extends AllPathObj> = MapObj<AllPathObj>;
function Fn<PathObj extends AllPathObj>({ path }: Props<PathObj>) {
const path2: AllPaths = path;
}
关于javascript - typescript :使用联合类型映射对象值无法按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65194787/