“Object”类型中缺少“string”类型的索引签名。ts(2322)

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

我想将我的自定义对象分配给 Prisma 包中的 JsonObject efied。这段代码生成错误,我不知道为什么:

interface JsonArray extends Array<JsonValue> {}
type JsonValue = string | number | boolean | JsonObject | JsonArray | null
type JsonObject = {[Key in string]?: JsonValue}
// ^ These are defined in Prisma package and I cannot change them

interface Object {
  name: string
}

let object : Object
let jsonObject : JsonObject 

// This line has error
jsonObject = object;

// Type 'Object' is not assignable to type 'JsonObject'.
// The 'Object' type is assignable to very few other types.
// Did you mean to use the 'any' type instead?
// Index signature for type 'string' is missing in type 'Object'.ts(2322)
typescript interface
3个回答
3
投票

首先,不要命名您的自定义对象类型

Object
。类型
Object
Object
值的内置类型。它可能会让人们感到困惑。我不确定您是想更新现有的
Object
类型还是只想创建一些自定义类型,这对于接口来说很重要,因为声明合并

考虑这个例子:

interface JsonArray extends Array<JsonValue> { }

type JsonValue = string | number | boolean | JsonObject | JsonArray | null

type JsonObject = { [Key in string]?: JsonValue }

interface CustomObject {
    name: string
}

declare let object: CustomObject
declare let jsonObject: JsonObject

// This line has error
jsonObject = object;

您遇到的错误意味着

jsonObject
已被索引。换句话说,这意味着您可以使用任何字符串来访问对象值。 例如:

jsonObject['hello'] // ok

然而对于

object
来说则不然。在
object
情况下,您只能使用
name
键来访问适当的值。您不可以使用
hello

object['hello'] // error

现在,想象一下 TS 允许您执行此操作的情况:

jsonObject = object;

jsonObject['hello'] // undefined, because  it has only `name` property

所以,如果你想让它可分配,你应该将索引添加到你的

CustomObject

interface CustomObject {
    [prop: string]: JsonValue
    name: number
}

或者,更有趣的是使用

type
关键字来声明
CustomObject
而不是
interface
:

interface JsonArray extends Array<JsonValue> { }

type JsonValue = string | number | boolean | JsonObject | JsonArray | null

type JsonObject = { [Key in string]?: JsonValue }

type CustomObject= {
    name: number
}

declare let object: CustomObject
declare let jsonObject: JsonObject

jsonObject = object; // no error

jsonObject.name

是的,

interface
type
之间的索引存在差异。请参阅我的答案文章

请记住,此操作是允许的:

jsonObject['hello'] // undefined but allowed

没有编译器错误,但不安全。


2
投票

这里有一些问题。

  • Object
    是内置的 JavaScript 数据类型。您应该将您的界面命名为其他名称,例如
    MyObject
    ,
  • 您正在声明一个变量
    object
    但它没有初始化,即它没有任何值。您不能在操作中使用它,如
    x = object
  • 您的界面未与
    JsonObject
    完全重叠。您可以修改界面或使用
    type
interface JsonArray extends Array<JsonValue> {}
type JsonValue = string | number | boolean | JsonObject | JsonArray | null
type JsonObject = {[Key in string]?: JsonValue}
// ^ These are defined in Prisma package and I cannot change them

type MyObject = {
  name: string
}

let anObject: MyObject = {name: "foo"}
let jsonObject: JsonObject 

// no error
jsonObject = anObject

typescript 游乐场尝试一下。


0
投票

我认为之前的答案并没有解决这个常见问题。 Prisma 描述了一种非常通用的 JSON 对象类型(带有索引签名),我们在现实生活中使用的特定类型几乎永远不够通用(想想你使用索引签名的现实生活类型的百分比)。

我的解决方案就是使用类型转换:

myObject as object
。然后它与 Prisma.JsonObject 兼容。

我确信我的对象可以转换为 JSON(例如,我知道它是通过 JSON 从外部 API 接收的,然后进行转换/验证 - 这里可能会出现什么问题?),我只想保存它而不会使代码膨胀,所以我我很确定这是处理这种情况的好方法。

我承认在某些罕见的情况下这不是一个好的解决方案(因为 JS 对象字段不能转换为 JSON,例如在具有循环引用的对象中),但坦率地说,我无法想象一个现实的情况您在 Prisma 中创建一个 Json 类型的字段,然后使用一个无法转换为 JSON 的对象。

© www.soinside.com 2019 - 2024. All rights reserved.