I want to assign my custom object to JsonObject efied in Prisma package. this code generates error that I don't know why:
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)
First of all, don't name your custom object type Object
. Type Object
is built in type for Object
value. It may confuse people. I'm not sure whether you want to update existing Object
type or you want just to create some custom type, it is important for interfaces because of declaration merging.
consider this example:
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;
The error you have means that jsonObject
is indexed. In other words it means that you can use any string to access the object values.
For instance:
jsonObject['hello'] // ok
Whereas it is not true for object
. In object
case you are allowed to use only name
key to access appropriate value. You are not allowed to use hello
.
object['hello'] // error
Now, imagine the situation where TS allows you to do this operation:
jsonObject = object;
jsonObject['hello'] // undefined, because it has only `name` property
SO if you want to make it assignable you should add indexing to your CustomObject
:
interface CustomObject {
[prop: string]: JsonValue
name: number
}
Or, what is more interesting use type
keyword for declaring CustomObject
instead of 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
Yes, there is a difference in terms of indexing between interface
and type
. See my answer and article
Please keep in mind that this operation is allowed:
jsonObject['hello'] // undefined but allowed
There is no compiler error but it is unsafe.