Within the code snippet provided, there are two instances of a Record<string, string[]>
. One declares itself directly as the Record
, while the other uses a type alias that refers to the same Record
type. When these are passed into a function along with an empty array (expected to be inferred as an empty string array by TypeScript), the first instance compiles successfully, but the second does not. This issue seems to arise from the type alias causing a problem. Is there a workaround for this situation? Should this be reported as a bug in TypeScript?
function foo<T>(record: Record<string, T>, entity: T) {
}
type StringArrayRecord = Record<string, string[]>;
function test() {
const working: Record<string, string[]> = {};
foo(working, []); // Compiles
const broken: StringArrayRecord = {};
foo(broken, []); // Does not compile
}
The error message is as follows:
Argument of type 'StringArrayRecord' is not assignable to parameter of type 'Record<string, never[]>'.
'string' index signatures are incompatible.
Type 'string[]' is not assignable to type 'never[]'.
Type 'string' is not assignable to type 'never'.
If an alternate type is used instead of string[]
as the second type parameter in the record, the same issue occurs whenever there is ambiguity in the type (such as a union type), for example:
type StringOrNumberRecord = Record<string, string | number>;
function test() {
const working: Record<string, string | number> = {};
foo(working, "string"); // Compiles
const broken: StringOrNumberRecord = {};
foo(broken, "string"); // Does not compile
}
(This behavior persists in both TypeScript 4.8 and 5.)
(One potential solution is to explicitly specify the type of the second parameter when calling foo
, such as
foo(broken, "string" as string | number);
. Another option is to specify the generic type parameter when invoking foo
, like foo<string | number>(broken, "string")
. However, it seems that neither of these should be necessary.)