转换对象属性,以便在TypeScript中保留隐式类型。

16 浏览
0 Comments

转换对象属性,以便在TypeScript中保留隐式类型。

我正在寻找一种转换函数或方法,可以让我保留TypeScript推断类型的能力(获得类型检查和代码提示)在结果对象上。在下面的示例中,C和相关的E是证明问题的情况。\n

class Wrapper {
    constructor(private val: T) { }
    value(): T {
        return this.val;
    }
}
// A
var wrappedNum = new Wrapper(1);
// TypeScript推断value()返回一个数字
wrappedNum.value().toFixed(1);
// B
var wrappedNumArray = [1, 2, 3].map(function(val) { return new Wrapper(val); });
// TypeScript推断对于数组中的每个元素,value()返回数字
wrappedNumArray[0].value().toFixed(1);
// C
// **在这个转换中,属性的类型丢失了**
function wrapObject(obj) {
    var targ = {};
    for(var key in obj) {
        targ[key] = new Wrapper(obj[key]);
    }
    return targ;
}
var wrappedObj = wrapObject({a: 1});
// TypeScript没有推断出wrappedObj上存在`a`
wrappedObj.a;
// D
// TypeScript推断出`a`及其类型
({ a: 1 }).a.toFixed(1);
// E
// **在这个转换中,属性的类型丢失了**
function noop(obj) {
    return obj;
}
// TypeScript没有推断出noop转换对象上存在`a`
noop({ a: 1 }).a;
// F
function getValue() {
    return { a: 1 };
}
// TypeScript推断出存在`a`及其类型
getValue().a.toFixed(1);

\n是否有一种方法可以使C和E的结构在保持对传递对象结构不可知的情况下,使类型推断工作?

0
0 Comments

问题:如何在TypeScript中使对象属性的隐式类型保持不变?

在上述内容中,提到了两种尝试解决这个问题的方法,分别是C和E。

在C中,作者提到了一种使用类似字典的类型并使用泛型进行映射的方法。具体实现是通过一个名为wrapObject的函数,接受一个泛型参数T和一个类型为T的对象obj。在函数内部,通过遍历obj的属性,并创建一个具有相同属性的对象targ,属性值为obj中对应属性的包装对象Wrapper。最后,返回targ。通过这种方式,实现了对象属性的隐式类型保持不变。

在E中,作者提到了使用泛型的方法。具体实现是通过一个名为noop的函数,接受一个泛型参数T和一个类型为T的对象obj。在函数内部,直接返回obj。通过这种方式,实现了对象属性的隐式类型保持不变。

然而,尽管E中的方法能够正确工作,但对于C而言却是错误的。在C中,wrappedObj.a表面上看起来是具有推断的number类型,但实际上是一个Wrapper类型。这种类型系统的强制转换与wrapObject上的返回类型注释相符。

作者提到,目前他并没有想到其他解决这个问题的方法。他希望对TypeScript更熟悉的人能够提供帮助。

总结一下,问题是如何在TypeScript中使对象属性的隐式类型保持不变。解决方法有两种尝试,分别是使用字典和泛型。然而,使用字典的方法在某些情况下可能会导致类型错误。对于目前的问题,尚未找到其他解决方法。希望能够得到更多熟悉TypeScript的人的帮助。

0