Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript interface where key name has known prefix but full key is unknown

Tags:

typescript

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[];
}
like image 566
d-_-b Avatar asked Oct 31 '25 21:10

d-_-b


1 Answers

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!  
});

Playground link to code

like image 103
jcalz Avatar answered Nov 03 '25 11:11

jcalz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!