typescript 泛型 : infer type from the type of function arguments?

标签 typescript typescript-generics

我有一个有 2 个参数的方法,我希望它从第一个参数推断一个类型。

例如,在下面的代码中,我想要类型 T功能create_C<T>firstArgument 推断所以返回类型为 create_C函数将是 C<type inferred from firstArgument>

interface C<T> { 
    firstArgument: A<T>;
    secondArgument: (obj: any) => T
}

export interface A<T> {
    type: T;
}

function create_C<T>(
    firstArgument: A<T>,
    secondArgument: (obj: any) => T
): C<T> {
    return {
        firstArgument,
        secondArgument
    }
}

但是,在下面的实现中,const c 的类型被推断为 C<{ prop2: number }> .但我希望它被推断为 C<B>我希望编译器抛出一个错误,指出 secondArgument 的返回类型不是类型 B
interface B { 
    prop1: string;
    prop2: number
}

export class B_Component implements A<B> {
    type: B = {
        prop1: "",
        prop2: 1
    };
}

const c = create_C(
    new B_Component(),
    () => ({ prop2: 2 })
)

我如何确保编译器抛出错误,指出 secondArgument 的返回类型不是类型 B ?

这是 Stackblitz 编辑器链接:https://stackblitz.com/edit/qqddsn

最佳答案

在您的函数签名中

declare function create_C<T>(a1: A<T>, a2: (obj: any) => T): C<T>;
T 有两个推理站点(“推理站点”的意思是“编译器可以用来尝试推断类型参数的类型的某个地方”)。一个站点来自 type第一个参数的属性 a1 ,另一个站点是第二个参数的返回类型a2 .编译器看起来像这样的调用
create_C(new B_Component(), () => ({ prop2: 2 });

并试图推断 T从两个站点。在这种情况下,有一个匹配项:both (new B_Component()).type{prop2: 2}可分配给 {prop2: number} .所以没有错误,你会得到 C<{prop2: number>出来。在另一种情况下,这可能正是您想要的编译器行为。

相反,您希望看到编译器仅使用 a1推断 T , 并验证 a2匹配它。也就是说,您想要 T(obj: any) => T成为 non-inferential type parameter (see microsoft/TypeScript#14829) .不幸的是,对此没有“官方”支持。但幸运的是,有一些解决方法通常可用于获得这种行为。

这是一种这样的技术:如果您从 T 更改推理站点中的类型参数至 T & {} ,它lowers the site's priority .所以编译器会倾向于推断 T首先从其他推理站点返回 T & {}一个如果它无法从其他地方推断出来。和类型T & {}T 非常相似(如果 T 是一个对象类型,那么它基本上是相同的)所以它不会改变太多语义。让我们试试看:
declare function create_C_better<T>(a: A<T>, b: (obj: any) => T & {}): C<T>;

开始:
const c2 = create_C_better(
    new B_Component(),
    () => ({ prop2: 2 }) // error!
    //    ~~~~~~~~~~~~~~ <-- prop1 is missing
)

const c3 = create_C_better(
    new B_Component(),
    () => ({ prop1: "all right", prop2: 2 })
); // C<B>

在那里,当 prop1 时你会得到你想要的错误丢失,当你修复它时,你会得到类型 C<B> 的输出如预期的。

好的,希望有帮助;祝你好运!

Link to code

关于 typescript 泛型 : infer type from the type of function arguments?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59055154/

相关文章:

typescript 泛型 : map with keys of type T[K] to values of T itself (grouping T[] by own property value)

javascript - TypeScript 泛型创建实例

angular - Ion-item-option 按钮需要点击两次

typescript - 将 FormGroup 映射到界面对象

javascript - 这两个 "extends"子句有什么区别?

reactjs - 为什么在使用泛型的特定设置中将可选字段的类型设置为未知?

类型的 typescript 传播运算符

javascript - 我们真的必须 OOPsify TypeScript 中的所有内容吗?

javascript - 在 TypeScript 中将类导出为 Node.js 模块

javascript - 在外部选项卡 url 应用程序中访问 Teams session 和其他信息