Issue
Is there a way to define an interface in which the keys have a known prefix (added_
, removed_
) but the full key is unknown?
For example, a valid object might be:
{
name: "",
added_abc: [1,2,3],
added_bcd: [2],
removed_abcd: [4,5],
removed_xyz: [],
}
I'd want to ensure an interface with:
interface myobject {
name: string;
added_*?: number[];
removed_*?: number[];
}
Solution
When TypeScript 4.4 is released, you will be able to leverage template string pattern literal index signatures, as implemented in microsoft/TypeScript#44512, and then this will work:
// TS4.4+
interface MyObject {
name: string;
[k: `added_${string}`]: number[];
[k: `removed_${string}`]: number[];
}
const myObject: MyObject = {
name: "",
added_abc: [1, 2, 3],
added_bcd: [2],
removed_abcd: [4, 5],
removed_xyz: [],
} // okay
const myBadObject: MyObject = {
name: "",
added_abc: [1, 2, 3],
addled_bcd: [2], // error!
}
Until then, there is no specific type in TypeScript which represents your requirements. You can use generic helper functions with template literal types in TS4.1 to TS4.3, but such functions are more complicated:
// TS 4.1-4.3
const asMyObject = <T extends { name: string } & { [K in keyof T]:
K extends `added_${string}` | `removed_${string}` ? number[] :
K extends "name" ? string :
never }>(t: T) => t;
const myObject2 = asMyObject({
name: "",
added_abc: [1, 2, 3],
added_bcd: [2],
removed_abcd: [4, 5],
removed_xyz: [],
}); // okay
const myBadObject2 = asMyObject({
name: "",
added_abc: [1, 2, 3],
addled_bcd: [2], // error!
});
Answered By - jcalz
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.