typescript 合并的结构化对象中的getter属性无法解释类型

i2byvkas  于 2023-04-07  发布在  TypeScript
关注(0)|答案(4)|浏览(482)

bounty已结束,回答此问题可获得+50声望奖励,奖励宽限期20小时后结束,A. L希望引起更多关注此问题。

为什么function g中的example无法解释类型?它将其视为any

function f (name : string) {
    return {
        name : name,
    }
}

function g (name : string) {
    return {
        ...f(name),
        get example () {
            return this.name + " example";
        }
    }
}

是否有不强制输出类型的变通方法?例如get example () : string
打字游戏场

9avjhtql

9avjhtql1#

在我看来,这是TypeScript中的一个Bug。
我可以进一步简化这个例子(Playground):

const x = {
    ...{
        name : "foo",
    },
    get example () {
        /* 'n' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.(7022) */
        const n = this.name; /* (property) name: string */
        /* const n: any */

        return n;
    },
    getexample () {
        const n = this.name;
        return n;
    },
};
hm2xizp9

hm2xizp92#

感谢@htho,我意识到我最初的答案是不正确的,问题似乎与传播运营商,通过更改为以下错误将消失:

//...
function g (name : string) {
    return {
        name: f(name).name,
        get example () {
            return this.name + " example";
        }
    }
}

console.log(g("John"))

即使您将getter的返回类型设置为string(get example():string ...)并在TS playground中运行console.log(g("John")),您也会看到this.name将返回undefined,并且无法按预期工作。
我会将你的代码重构为下面的代码,它会更易读,更容易被其他开发人员理解:

class Person {
    name: string

    constructor(name: string) {
        this.name = name;
    }
    get example() {
        return this.name + " example"
    }
}
function g(name: string) {
    return new Person(name)
}

console.log(g("John").example)
pgpifvop

pgpifvop3#

我的猜测是,在推断类型时,Typescript对你来说是“好”的,但是因为hashMap不是按照它们声明的顺序处理的,所以我们不能确定f(name)将在get example()之前执行。
因此,您必须确保函数f在之前执行,例如

function f(name: string) {
  return {
    name: name,
  };
}

function g(name: string) {
  const res = {...f(name)}

  return {
    name: res.name,
    get example() {
      return this.name + " example";
    }
  };
}

console.log(g("Max").example); // "Max example"

这不是一个bug,因为当你在原始示例中解构函数时,如果调用this.name的结果将产生“undefined”。

function f(name: string) {
  return {
    name: name,
  };
}

function g(name: string) {
  return {
    ...f(name),
    get example() {
      return this.name + " example";
    }
  };
}

console.log(g("Max").example); // "undefined example"

编辑:经过一些研究,似乎问题来自于无法改变对象的扩展操作符,因为Object.assign将做doc。
因此,这将工作,即使在typescript抱怨:

function f(name: string) {
  return { name: name }
}

function g(name: string) {
  const obj1 = { get example() {return this.name + " example"}};
  return Object.assign(obj1, f(name))
}

console.log(g("Max").example); // "Max example"
sczxawaw

sczxawaw4#

你只需要定义return to example并访问f functio的正确元素。我也做了return的接口,但这是可选的。看这个例子:

// interface to return of F function

interface ReturnFName {
    name: string;
}

function f (name : string): ReturnFName {
    return {
        name : name,
    }
}

function g (name : string) {
    // get the element name and store it in a variable
    const nameF = f(name).name;
    return {
        get example (): string {
            return nameF+ " example";
        }
    }
}

console.log(g('carol'));

在playground上运行代码

相关问题