Reputation: 9722
I was hoping I could have an interface like:
interface Item {
[ index: string ] : string | number | Item,
id: number,
}
So that an Item, can have any properties with string/number/object values, BUT-- if an id property is used, it MUST be a number.
Is this possible?
EDIT
I originally asked this, but then tested it out and what I did seems to work fine, UNLESS I am using optional attributes...
If I do this, then I get a typescript error:
interface Item {
[ index: string ] : string | number | Item,
id?: number,
}
In order to get this to work, I have to do:
interface Item {
[ index: string ] : string | number | Item | undefined,
id?: number,
}
Which I don't think I want all my other properties to be potentially undefined... Is there another way to have id
be optional?
EDIT AGAIN
Turns out even with the | undefined
this doesn't work.. If I do the following:
let i : Item = { id: 123, foo: { bar: { id: 555} } };
console.log(i.foo.bar.id);
I get errors about "object is possibly undefined"
Upvotes: 1
Views: 201
Reputation: 2750
Answer already provided by "noob" but extending a Record seems to work fine:
type Test = Record<string, string|number> & {
id?: number;
};
let t0: Test = {
foo: 1,
bar: "2"
}
let t1: Test = {
id: "1",
foo: 1,
bar: "2"
}
let t2: Test = {
id: 1,
foo: 1,
bar: "2"
}
You will see an error:
Errors in code Type 'string' is not assignable to type 'number | undefined'.
Upvotes: 0
Reputation: 580
According to the doc, you can as long as the type of id
is a subtype of [index: string]
interface NumberDictionary {
[index: string]: number;
length: number; // ok
name: string; // not ok
// Property 'name' of type 'string' is not assignable to 'string' index type 'number'.
}
interface NumberOrStringDictionary {
[index: string]: number | string;
length: number; // ok, length is a number
name: string; // ok, name is a string
}
Edit:
I'm not sure if this is the best way but this seems to work
interface Item1 {
[ index: string ] : string | number | Item;
}
interface Item2 {
id?: number;
}
type Item = Item1 & Item2
Also "object is possibly undefined" error can be solved with optional chaining
let i : Item = { id: 123, foo: { bar: { id: 555} } };
console.log(i.foo?.bar?.id);
Upvotes: 1