When attempting to change an object's type to a generic array using the as
keyword, I encountered an error.
interface TestType {
action: TestGeneric<number>[]
}
type TestGeneric<T> = {
[key: string]: T
}
const func = () => {
const Test = {
action: [
{ a: 3 },
{ e: 4 }
]
}
console.log(Test as TestType)
}
The error message states:
Conversion of type '{ action: ({ a: number; e?: undefined; } | { e: number; a?: undefined; })[]; }' to type 'TestType' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Types of property 'action' are incompatible.
Type '({ a: number; e?: undefined; } | { e: number; a?: undefined; })[]' is not comparable to type 'TestGeneric[]'.
Type '{ a: number; e?: undefined; } | { e: number; a?: undefined; }' is not comparable to type 'TestGeneric'.
Type '{ e: number; a?: undefined; }' is not comparable to type 'TestGeneric'.
Property 'a' is incompatible with index signature. Type 'undefined' is not comparable to type 'number'.
When declaring with type (Test: TestType = ...
) or using the unknown
keyword, no error is thrown. However, when trying to import a local JSON file, type checking becomes crucial for me.
My tsconfig.json setup (same as Create-React-App) looks like:
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}
Upon further investigation, it seems that the issue lies with arrays and index signatures rather than generics. Link
() => {
const test = [{a: 1}, {b: 2}]
type TestType = {[key: string]: number}[]
console.log(test as TestType);
}
The error now reads:
Conversion of type '({ a: number; b?: undefined; } | { b: number; a?: undefined; })[]' to type 'TestType' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Type '{ a: number; b?: undefined; } | { b: number; a?: undefined; }' is not comparable to type '{ [key: string]: number; }'.
Type '{ b: number; a?: undefined; }' is not comparable to type '{ [key: string]: number; }'.
Property 'a' is incompatible with index signature. Type 'undefined' is not comparable to type 'number'.
In my second edit, I changed data types from arrays to index signatures. Link
() => {
const test = {0:{a: 1}, 1: {b: 2}}
type TestType = {[key: string]: {[key: string]: number}}
console.log(test as TestType);
}
After reviewing the answer, I realized that data types should be declared separately. What sets this code apart from the earlier version? Why does this code not produce an error?