我正在处理一些代码,这些代码可以解析属性值的通用类型,并且不允许提供错误的值。但是,当我从TValue
更改为(t: TValue) => TValue
时,键入TValue
并不会解决更多。现在是未知的{}
类型,而不是另外number
没有功能的示例。工作正常
type ProtoOf<T> = Pick<T, keyof T>;
function decorate<TValue>(value: TValue) {
return <T extends { [KA in TKey]: TValue }, TKey extends keyof T>(
proto: ProtoOf<T> & { [P in TKey]: TValue },
propertyKey: TKey
) => {};
}
class Foo {
// TS error: none
// Result: EXPECTED
@decorate(1) bar: number = 1;
// TS Error:
// Types of property 'wrongBar' are incompatible
// Type 'number' is not assignable to type 'string'
// Result: EXPECTED
@decorate('') wrongBar: number = 1;
}
具有功能的示例。不能按预期工作
type ProtoOf<T> = Pick<T, keyof T>;
function decorate<TValue>(getValue: (t: TValue) => TValue) {
return <T extends { [KA in TKey]: TValue }, TKey extends keyof T>(
proto: ProtoOf<T> & { [P in TKey]: TValue },
propertyKey: TKey
) => {};
}
class Foo {
// TS Error: Operator '+' cannot be applied to types '{}' and '1'
// Result: NOT EXPECTED: because we can assign `number` to `number`
@decorate(v => v + 1) bar: number = 1;
// TS error: none
// Result: NOT EXPECTED: we should have error, we cannot assign `string` to `number`
@decorate(v => v + '') wrongBar: number = 1;
}
在具有函数的示例中,我希望TValue
等于number
,在没有函数的示例中,
答案 0 :(得分:1)
这是一个known issue,从GitHub注释中可以看出。在这里总结:
当前,类型推断无法按您希望的方式工作,因为编译器将原始推断等同于以下内容:
const barDeco = decorate(v => v + 1); // error
barDeco(Foo.prototype, "bar");
const wrongBarDeco = decorate(v => v + '');
wrongBarDeco(Foo.prototype, "wrongBar");
并且decorate()
和barDeco
中对wrongBarDeco
的调用没有足够的类型信息供编译器推断通用类型,因此被推断为{{1} },导致很多悲伤。装饰器基本上是咖喱函数{}
,并且要解决此问题,编译器必须从f(x)(y)
的类型推断f
的类型,这是一种新的上下文类型。也许装饰器可能是特殊情况下的推理。通常,使用咖喱函数来完成此操作可能是一个巨大的突破性变化。
目前,解决此问题的唯一方法是在调用装饰器时手动指定通用参数,如下所示:
y
或手动注释回调,如
class Foo {
@decorate<number>(v => v + 1) bar: number = 1; // okay
@decorate<number>(v => v + '') wrongBar: number = 1; // error
}
这些变通办法不是最佳解决方案,但是它们确实有效,因此除非解决Microsoft/TypeScript#2607,否则您有某种处理问题的方法。有很多很多未解决的问题,所以我不希望看到这个问题有太多进展。如果有更多的人去解决这个问题并给出一个解决方案,并描述令人信服的用例和令人信服的原因,那么这种可能性就会增加。既然您已经完成了此操作,那么我认为您没有什么可以做的,而是继续前进。如果将来的读者对此有所关注,则可以在GitHub中查看问题并做出贡献。
对不起,您没有更好的答案。祝你好运!