Búsqueda de sitios web

typescript - Falta la firma de índice para el tipo 'string' en el tipo 'Object'.ts(2322)


Quiero asignar mi objeto personalizado al JsonObject definido en el paquete Prisma. Este código genera un error que no sé por qué:

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)

Respuesta #1

En primer lugar, no nombres tu tipo de objeto personalizado Object. El tipo Object es un tipo incorporado para valores Object. Esto puede confundir a la gente. No estoy seguro de si quieres actualizar el tipo Object existente o si solo quieres crear algún tipo personalizado, esto es importante para las interfaces debido a la fusión de declaraciones.

considera este ejemplo:

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;

El error que tienes significa que jsonObject está indexado. En otras palabras, significa que puedes usar cualquier cadena para acceder a los valores del objeto. Por ejemplo:

jsonObject['hello'] // ok

Mientras que no es cierto para object. En el caso de object solo se permite usar la clave name para acceder al valor correspondiente. No se permite usar hello.

object['hello'] // error

Ahora, imagina la situación en la que TS te permite realizar esta operación:

jsonObject = object;

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

Así que si quieres que sea asignable, deberías agregar indexación a tu CustomObject:

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

O, lo que es más interesante, usa la palabra clave type para declarar CustomObject en lugar de 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

Sí, hay una diferencia en términos de indexación entre interface y type. Mira mi respuesta y artículo

Por favor, tenga en cuenta que esta operación está permitida:

jsonObject['hello'] // undefined but allowed

No hay error de compilación, pero es inseguro.

Respuesta #2

Hay algunos problemas aquí.

  • Object es un tipo de dato incorporado en JavaScript. Deberías nombrar tu interfaz de otra manera, por ejemplo, MyObject,
  • Estás declarando una variable object pero no está inicializada, es decir, no tiene ningún valor. No puedes usarla en operaciones como x=object,
  • Su interfaz no se superpone completamente con JsonObject. Puede modificar la interfaz o usar 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

Pruébalo en el playground de TypeScript.

Artículos relacionados