Home > Blockchain >  How to type a parameter as any interface with values of a certain type in Typescript
How to type a parameter as any interface with values of a certain type in Typescript

Time:12-13

I have a function that I would like to accept any interface that contains only values of type T. For example:

// library function
function print(thing: /* any interface that is boolean | string */) {
    console.log(thing)
}

// user defined interface
interface Machine {
    powered: boolean
}

// user defined interface
interface Animal {
    sound: string
}

// user defined interface
interface Person {
    age: number
}

let blender: Machine = {
    powered: false
}

let cat: Animal = {
    sound: "meow"
}

let person: Person = {
    age: 24,
}

print(blender); // all good
print(cat);     // all good
print(person);  // nope

I tried a mapped type (and Record<string, T>), but it appears that Typescript doesn't let you cast interfaces to those. How should I type thing to accept any interface with values of type boolean | string?

CodePudding user response:

If the function parameter thing type is Record<string, T>, it can accept only arguments that extend { [k: string]: T }, i.e. with at least string index signature, which is not included in well-defined interfaces like Animal or Machine.

To accept any kind of interface with some unknown but well-defined keys (i.e. which may not have an index signature), you can use a generic parameter type that "extends its own keys":

function print<T extends { [K in keyof T]: string | boolean }>(thing: T) {
    console.log(thing)
}

print(blender); // all good
print(cat);     // all good
print(person);  // nope Error: Type 'number' is not assignable to type 'string | boolean'.

const rec: Record<string, string> = {}
print(rec); // Also okay

Playground Link


Another possibility would be to use the generic parameter type only to infer the passed argument keys:

function print<T>(thing: Record<keyof T , string | boolean>) {
    console.log(thing)
}

Playground Link

  • Related