具有嵌套属性的类型化对象文字无法获取智能感知

时间:2020-05-03 09:55:42

标签: typescript visual-studio-code javascript-objects intellisense

我正在尝试使用Typescript改善我的项目,但我不知道如何使以下内容正常工作。

说我有一个像这样简单的函数表达式

const foo = (objectLiteral: any): void => {
  console.log(objectLiteral)
}

现在,我将像这样使用它。

foo({
  name: 'guybrush',
  nestedProperties: {
    gunPowderAmount: 1
  },
  speak () {
    // First issue, "this" is any type. I don't get any intellisense for the properties 
    // within the object.
    // this.
  }
})

根据我在语音函数中的注释,“ this”具有任何类型,并且我无法访问该对象的任何属性。我认为这与此https://github.com/microsoft/TypeScript/issues/11072有关。

我知道这与打字稿无关-但是-我要到达那里。

然后我假设,因为我使用的是打字稿,所以我可以利用类型,太酷了! 因此,我的代码更改为以下内容:

type MappedCharacter = {
  name: string;
  speak: () => void;
  nestedProperties: { [key: string]: number | string };
}

const foo2 = (objectLiteral: MappedCharacter) => {
  console.log(objectLiteral)
}

我将像这样使用它:

foo2({
  name: 'guybrush',
  nestedProperties: {
    gunPowderAmount: 1
  },
  speak () {
    // Second issue. Now "this" has access to the properties, but NOT
    // the one which are NESTED into "nestedProperties"
  }
})

很酷,我现在可以访问“ this”,并且可以将属性“ name”和“ nestedProperties”作为目标。

但是,嘿,“ nestedProperties”还有其他属性!他们在哪里?

最终测试,我将摆脱函数表达式,而仅对对象进行测试。

const objectLiteral: MappedCharacter = {
  name: 'guybrush',
  nestedProperties: {
    gunPowderAmount: 1
  },
  speak () {
    // Third issue. Even if not used in a function, "this.nestedProperties" can't dig any 
    // deeper.
    // this.nestedProperties.
  }
}

从语音功能中的注释来看,再次使该嵌套属性起作用没有运气。

我也没有运气尝试过,将我的类型更改为:

type MappedCharacter = {
  name: string;
  speak: () => void;
  nestedProperties: keyof MappedCharacter['nestedProperties'];
}


'nestedProperties'的结果直接或间接在其自己的类型注释中引用

编辑: 我不想为“ nestedProperties”对象定义类型。 我只是希望它尽可能通用,因为我无法预见它可以拥有什么样的属性。

EDIT2: 如果我有一个普通的对象文字,没有任何类型,vscode可以确定这些属性,使其尽可能嵌套。我想用类型实现相同的行为。 我通常在具有Vetur扩展功能的项目中使用Vuejs,并且当为数据函数定义不同的属性时,智能感知就可以了。

任何人都可以阐明这个问题吗? 难题的缺失部分是什么?

1 个答案:

答案 0 :(得分:-1)

定义MappedCharacter类型时,基本上是说nestedProperties具有 some 属性。您没有定义哪个,因此编译器没有此信息。

然后,您创建objectLiteral对象,其中nestedProperties具有gunPowderAmount属性-但这仅适用于该特定对象,并且在该特定时刻。仍然会根据speak()类型对MappedCharacter函数进行类型检查,该类型在任何地方都没有定义gunPowderAmount属性。

我建议,如果您知道MappedCharacter会有哪些不同的特性,请这样定义:

type MappedCharacter<TProps> = {
  name: string;
  speak: () => void;
  nestedProperties: TProps
}

type GuybrushProps = {
  gunPowderAmount: number
}

const objectLiteral: MappedCharacter<GuybrushProps> = {
  name: 'guybrush',
  nestedProperties: {
    gunPowderAmount: 1
  },
  speak () {
    // Then, intellisense here should work as you expect it to
  }
}