How to declare Typescript type that is AnyRecord OR an object array?
In short, I want to do this:
interface Rec {
key: string;
}
type RecordOrList = Record<string, any> | Rec[];
So, RecordOrList
is either some object, or a list of specific objects.
However, typescript here seems to treat arrays of Rec
-s as Any Records. For example, this is valid code, but I was expecting it to be a type error ("int instead of string").
const x: RecordOrList = [{
key: 123,
}];
https://www.typescriptlang.org/play?ts=4.5.4#code/JYOwLgpgTgZghgYwgAgEoQcg3gWAFDLIDWEAngFzIDOYUoA5gNz4C+++YpADiuggPZQAJgHkoAGWA1kAXjQZBQgDw06IegBpkcEKQB8yAD7yEAbQC6zPPgEhpAD0p9FYydLmncBYmUoBGACYAZg1WSyA
How can I make the code above type checked?
The issue you're having here is that arrays themselves are - surprisingly - a valid Record<string, any>
(specifically, it's a Record<"length", number>
).
// Valid. WTF?
const x : Record<string, any> = [];
const a : keyof [] = "length"; // Valid
const b : keyof [] = "bogus"; // Invalid
Object.getOwnPropertyNames(x); // => ["length"]
Instead of any
, you could use unknown
here:
interface Rec {
key: string;
}
type RecordOrList = Record<string, unknown> | Rec[];
// Type error as expected
const x: RecordOrList = [{
key: 123,
}];
// Works just fine
const y: RecordOrList = {key: 123}
const z: RecordOrList = [{
key: "123",
}];
Or just narrow your Record value type to a list of scalar types.