首页 > 解决方案 > Typescript 类型匹配对象,其 valueOf 最终返回一个字符串

问题描述

我过度设计了与 astring或对象匹配的类型,该对象valueOf()在递归评估时最终返回 a string

type Stringable = string | StringableObject;
interface StringableObject {
    valueOf(): Stringable;
}

let x: Stringable;

// should work:
x = 'foo';

x = {
    valueOf() { return 'foo'; }
};

x = {
    valueOf() {
        return {
            valueOf() { return 'foo'; }
        };
    }
};

// should not work but do:
x = {}; // valueOf() returns an object -- a reference to x, itself

x = {
    valueOf() { return 1; } // valueOf() returns a number
};

Object.prototype.valueOf(),当没有被覆盖时,返回一个object,而不是一个string,所以我很困惑为什么最后这些案例编译,以及我需要改变什么以使它们不编译。

我怀疑我需要创建一个使用infer关键字的泛型类型,但我仍在尝试了解如何infer正确使用。

奇怪的是,如果我更改valueOffoo,它会达到我的预期。

type Stringable = string | StringableObject;
interface StringableObject {
    foo(): Stringable;
}

// do not compile
x = {};

x = {
    foo() { return 1; }
};

x = {
    foo() {
        return {
            foo() { return 1; }
        };
    }
};

我认为它必须与自身的性质有关,或者与原型上valueOf()的事实有关,而不是对象本身的定义。valueOf()但是,我不知道为什么会这样。

标签: typescripttypescript-typings

解决方案


这里有一些误解,所以我将尝试单独解决每个误解,希望这有助于解释为什么您的代码没有产生您期望的结果。

Object.prototype.valueOf(),当没有被覆盖时,返回一个对象,而不是一个字符串,所以我很困惑为什么最后这些案例编译,以及我需要更改什么以使它们无法编译。

valueOf()返回调用它的 Object 的原始值。字符串字面量(例如'foo')被 JavaScript 视为原语,但由于原语没有属性,JavaScript 将原语强制转换为对象(实际上它会尽可能地强制任何类型以使操作有效)以便允许原语将是无效类型的操作。查看这篇 StackOverflow 帖子,了解有关对象强制的更多信息。这对您来说意味着它valueOf()可能根本不一定返回 Object,而是调用它的任何类型的原始值:

> "foo".valueOf()
'foo'
> let x;
> x = {}; x.valueOf()
{}
> x = 10; x.valueOf()
10

我过度设计了一个匹配字符串或对象的类型,其 valueOf() 在递归评估时最终返回一个字符串。

StringableObject接口没有描述其valueOf()方法最终将返回字符串的类型。它确实描述了一个类型,该类型的valueOf()方法将返回一个带有valueOf()方法的类型,该方法将返回一个带有方法的类型valueOf(),依此类推,这正是您的第一个代码块中这一行所发生的情况:

x = {};

x正在分配给一个 Object 字面量,该字面量可以被强制转换为一个Object,其valueOf()方法返回一个新的原语,该原语也有一个valueOf()方法,该方法产生一个可以被强制转换为 an 的原语,Object以此类推,以此类推。

在您的第二个代码块中,您将valueOf()方法更改为foo(),它不作为全局Object类型的方法存在,因此不能满足valueOf()您原来StringableObject创建的无限循环。

希望这可以帮助。


推荐阅读