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

问题描述 投票:0回答:5

为什么

example
中的
function g
无法解释类型?它认为它是
any

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

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

是否有不强制输出类型的解决方法?例如

get example () : string

打字稿游乐场

typescript
5个回答
0
投票

对我来说,这看起来像是 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;
    },
};

0
投票

感谢@htho,我意识到我最初的答案是不正确的,问题似乎出在扩展运算符上,通过更改为以下内容,错误将会消失:

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

console.log(g("John"))

即使您将 getter 的返回类型设置为字符串(

get example():string ...
)并在 TS Playground 中运行
console.log(g("John"))
,您也会看到
this.name
将返回未定义并且无法按预期工作。

我会将您的代码重构为以下内容,其他开发人员将更容易阅读和理解:

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)


0
投票

我的猜测是,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"

这不是一个错误,因为如果在解构原始示例中的函数时调用,

this.name
的结果将产生“未定义”。

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

因此,即使在打字稿抱怨中,这也适用:

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" 

0
投票

您只需要定义返回示例并访问 f 函数的正确元素即可。我也做了返回的接口,但是是可选的。看例子:

// 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

上运行代码

0
投票

最好的解决方案(也许只是解决方法)是为其他函数创建一个变量并使用它而不是

this

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

function g (name : string) {
    const toMerge = f(name)
    return {
        ...toMerge,
        get example () {
            return toMerge.name + " example";
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.