【问题标题】:Argument not allowed with keyof ("Expected 0 arguments, but got 1")keyof 不允许使用参数(“预期 0 个参数,但得到 1”)
【发布时间】:2018-10-10 01:10:47
【问题描述】:

尝试以递归/嵌套方式实现基本属性为KnockoutObservable<Primitive> 类型的类型:

export type Primitive = string | number | boolean | undefined | null;

export type KnockoutMappedProperty<T> =  T extends Primitive ? KnockoutObservable<T> : KnockoutMappedType<T>;

export type KnockoutMappedType<T> = {
    [Property in keyof T]: KnockoutMappedProperty<T[Property]>;
};

interface KnockoutObservable<T> extends KnockoutSubscribable<T>, KnockoutObservableFunctions<T> {
    (): T;
    (value: T): void;
    /*...*/
}

调用不带参数的函数编译:

const v1: KnockoutMappedType<{ prop: boolean }> = null;
const propValue: boolean = v1.prop();

如果(value: T): void; 在KnockoutObservable&lt;T&gt; 中不存在,则传递参数不会编译:

v1.prop(true); // Gives compiler error: Expected 0 arguments, but got 1

Intellisense 告诉我 v1.prop 的类型为 KnockoutObservable&lt;true&gt; | KnockoutObservable&lt;false&gt;。为什么某些东西会被拆分成一个应该只是 KnockoutObservable&lt;boolean&gt; 的联合类型?

以下再次编译正常:

const prop: KnockoutObservable<boolean> = v1.prop;
prop(true);

为什么需要引入KnockoutObservable&lt;boolean&gt;类型的变量?

Playground link

【问题讨论】:

    标签: typescript


    【解决方案1】:

    问题是条件类型分布在联合上,如docs 中所述。虽然一开始可能并不明显,boolean 是一个联合,联合 true | false。这意味着映射的prop1 将是KnockoutObservable&lt;true&gt; | KnockoutObservable&lt;false&gt; 类型。这意味着唯一可调用的签名将是通用签名,即没有任何参数的签名。

    要停止分发行为,您可以将类型参数穿在一个元组中(因为分发只发生在裸类型参数上)

    export type Primitive = string | number | boolean | undefined | null;
    
    export type KnockoutMappedProperty<T> =  [T] extends [Primitive] ? KnockoutObservable<T> : KnockoutMappedType<T>;
    
    export type KnockoutMappedType<T> = {
        [Property in keyof T]: KnockoutMappedProperty<T[Property]>;
    };
    
    interface KnockoutObservable<T> extends KnockoutSubscribable<T>, KnockoutObservableFunctions<T>  {
        (): T;
        (value: T): void;
        /*...*/
    }
    
    const v1: KnockoutMappedType<{ prop: boolean }> = null;
    const propValue: boolean = v1.prop();
    v1.prop(true); // ok
    

    【讨论】:

      猜你喜欢
      • 2020-11-07
      • 1970-01-01
      • 2022-01-24
      • 2018-08-14
      • 1970-01-01
      • 1970-01-01
      • 2021-07-29
      • 2021-08-22
      • 2019-08-28
      相关资源
      最近更新 更多