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