I have a scenario where I want to achieve something similar to the following:
type Whoozit = string | number
type WhoozitMap = {[key: string]: (x: Whoozit) => boolean}
const whoozit: WhoozitMap = {
cheese: (x: string) => x === 'cheese',
digit: (x: number) => x < 10
}
However, the above code doesn't work as intended. The type of the functions in the map must be Whoozit
, not just string
or number
. So, there are two ways to fix this issue:
const whoozit: WhoozitMap = {
cheese: (x: Whoozit) => { if (isString(x)) { return x === 'cheese' } else { return false } },
digit: (x: number) => { if (isNumber(x)) { return x < 10 } else { return false } },
}
// Although this is a solution, it adds unnecessary complexity as
// my code runtime can handle selecting the correct key from the map
or
type WhoozitMap = {[key: string]: (x: any) => boolean}
// This approach is cleaner, but it sacrifices all type safety within the map
Is there a way to express what I want in Typescript? Specifically, the following code snippet should compile:
const whoozit: WhoozitMap = {
cheese: (x: string) => x === 'cheese',
digit: (x: number) => x < 10
}
... whereas this example should not be valid?
const whoozit: WhoozitMap = {
cheese: (x: string) => x === 'cheese',
list: (x: number[]) => x.includes(22) // ❌ number[] does not extend Whoozit
}
Check out the Typescript Playground.