我有以下示例来说明我想要得到的内容。
const v1: { type: "S"; payload: string } = { type: "S", payload: "test" };
const v2: { type: "N"; payload: number } = { type: "N", payload: 123 };
type Actions = typeof v1 | typeof v2;
const findByType = <A extends Actions>(type: A["type"]) => (
action: Actions
): action is A => action.type === type;
const filterWithBothNameAndType = [v1, v2].filter(findByType<typeof v1>("S"));
console.log(filterWithBothNameAndType[0].payload.trim());
const findByTypeDoesntWork = <A extends Actions, T extends A["type"]>(type: T) => (
action: Actions
): action is A => action.type === type;
const filterWithJustType = [v1, v2].filter(findByTypeDoesntWork("S"));
console.log(filterWithJustType[0].payload.trim());
Run Code Online (Sandbox Code Playgroud)
我有findByType具有正确类型信息的函数filterWithJustType,我有具有我喜欢的 api 的函数,但它丢失了类型信息。我希望 api 只是filter("S")不传递泛型类型。到目前为止,它看起来只适用于类,instaceof但我想让它适用于普通对象。
Mat*_*vic 12
您可以使用Exclude或Extract正如文档中提到的,例如:
type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d"
type T01 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c"
type T02 = Exclude<string | number | (() => void), Function>; // string | number
type T03 = Extract<string | number | (() => void), Function>; // () => void
Run Code Online (Sandbox Code Playgroud)
它不起作用,因为它要求编译器做出假设,如果扩展的某个类型Actions具有type文字类型 的成员S,那么它一定是typeof v1。
一般来说,这个假设是不安全的,因为extends Actions约束非常弱,并且可以编译:
const v3: { type: "S"; payload: boolean } = { type: "S", payload: false };
const filterWithJustType3 = [v1, v2, v3].filter(findByTypeDoesntWork("S"));
Run Code Online (Sandbox Code Playgroud)
顺便说一句,它不会在strictFunctionTypes打开的 2.6 中进行编译,但类型推断没有利用此选项引入的额外健全性,并且不清楚它是否应该这样做。
但是有一种方法可以明确地告诉编译器,只能从其成员的类型明确地推断出联合成员type。您只需要自己建立类型映射:
const v1: { type: "S"; payload: string } = { type: "S", payload: "test" };
const v2: { type: "N"; payload: number } = { type: "N", payload: 123 };
interface ActionMap {
S: typeof v1;
N: typeof v2;
}
type Actions = ActionMap[keyof ActionMap];
const findByTypeWorks = <T extends keyof ActionMap>(type: T) => (
action: Actions
): action is ActionMap[T] => action.type === type;
const filterWithJustType = [v1, v2].filter(findByTypeWorks("S"));
console.log(filterWithJustType[0].payload.trim());
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3736 次 |
| 最近记录: |