Typescript 不允许使用keyof的参数(“应为0个参数,但得到1”)

Typescript 不允许使用keyof的参数(“应为0个参数,但得到1”),typescript,Typescript,尝试以递归/嵌套方式实现一种类型,其中基本属性的类型为KnockoutObservable: export type Primitive = string | number | boolean | undefined | null; export type KnockoutMappedProperty<T> = T extends Primitive ? KnockoutObservable<T> : KnockoutMappedType<T>; exp

尝试以递归/嵌套方式实现一种类型,其中基本属性的类型为
KnockoutObservable

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;
    /*...*/
}
Intellisense告诉我,
v1.prop
属于
KnockoutObservable | KnockoutObservable
类型。为什么某些东西被拆分成一个应该是可观察的联合类型

以下代码再次编译为罚款:

const prop: KnockoutObservable<boolean> = v1.prop;
prop(true);
const-prop:KnockoutObservable=v1.prop;
道具(真实);
为什么我需要引入类型为
KnockoutObservable
的变量


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

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

export type Primitive=string | number | boolean | undefined | null;
导出类型KnockoutMappedProperty=[T]扩展[Primitive]?KnockoutObservable:KnockoutMappedType;
导出类型KnockoutMappedType={
[keyof T中的属性]:KnockoutMappedProperty;
};
接口KnockoutObservable扩展了KnockoutSubscribable、KnockoutObserveFunctions{
():T;
(值:T):无效;
/*...*/
}
const v1:KnockoutMappedType=null;
常量propValue:boolean=v1.prop();
v1.道具(正确);//好啊
v1.prop(true); // Gives compiler error: Expected 0 arguments, but got 1
const prop: KnockoutObservable<boolean> = v1.prop;
prop(true);
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