Let's say I want to make a function called doThing
that takes a generic. When using this function, I intend to manually input the generic with an interface which could have any keys, but the values should always be strings. I would like TypeScript to give me an error if any of the interface's values are not strings, like this:
function doThing<T extends ???> {
// do a thing
}
interface GoodInterface {
foo: string
bar?: string
}
interface BadInterface {
foo: number
bar: string
}
doThing<GoodInterface>() // should work
doThing<BadInterface>() // should give a type error
Note that in GoodInterface
, the optional bar
key with string value is still accepted.
What would the generic have to extend to achieve this behavior? My initial thought was to extend Record<string, string>
, but that gave me the error Index signature for type 'string' is missing in type 'GoodInterface'
when I tried. I could add the index signature to the interfaces I plan to use, but I would prefer not to.
Let's say I want to make a function called doThing
that takes a generic. When using this function, I intend to manually input the generic with an interface which could have any keys, but the values should always be strings. I would like TypeScript to give me an error if any of the interface's values are not strings, like this:
function doThing<T extends ???> {
// do a thing
}
interface GoodInterface {
foo: string
bar?: string
}
interface BadInterface {
foo: number
bar: string
}
doThing<GoodInterface>() // should work
doThing<BadInterface>() // should give a type error
Note that in GoodInterface
, the optional bar
key with string value is still accepted.
What would the generic have to extend to achieve this behavior? My initial thought was to extend Record<string, string>
, but that gave me the error Index signature for type 'string' is missing in type 'GoodInterface'
when I tried. I could add the index signature to the interfaces I plan to use, but I would prefer not to.
1 Answer
Reset to default 2This one right here works
Partial
is used to indicate that T
can extend types with optional properties.
Record
is the object type, keyof T
are the keys of the generic type T
(the keys of the interface that will be passed as a generic argument), string
means that the values of properties can only be strings.
declare function doThing<T extends Partial<Record<keyof T, string>>>(): void;
interface GoodInterface {
foo: string
bar?: string
}
interface BadInterface {
foo: number
bar: string
}
doThing<GoodInterface>() // Works
doThing<BadInterface>() // Types of property 'foo' are incompatible.
{bar?: string}
but reject{bar: string | undefined}
? – jcalz Commented Feb 7 at 23:08