Reputation: 596
I have an interface which has a few properties with certain types
interface dummyInterface {
propA: string,
propB: boolean,
propC: number,
}
Props A through C are mandatory, but objects of this type can also include any number of additional properties with any name. However, I would like to force all additional properties to be of type string
. I know it can't be done by adding something like
{
.
.
.
[additionalProp: string]: string
}
since this would contradict PropB
and PropC
which are boolean
and number
respectively.
Is there any way in which I can accomplish that?
Upvotes: 0
Views: 1727
Reputation: 3629
You can achieve that with type intersection:
interface MandatoryProps {
numberProp: number;
boolProp: boolean;
}
type TypeWithMandatoryAndOptionalProps =
// For mandatory props:
MandatoryProps &
// For optionals:
Record<string, string>;
declare const foo: TypeWithMandatoryAndOptionalProps;
foo.blablabla; // string
foo.numberProp; // number
foo.boolProp; // boolean
UPD. I think I've rushed a bit with the answer. Whereas suggested type seems to solve the issue with defining such a type, there's still a bunch of issues with using it (explained by TS maintainers in the issue linked in comments below). You can try to solve the issue with assigning a value to a variable with such a type by casting through any
or using Object.assign
:
const foo = <TypeWithMandatoryAndOptionalProps><any>{/* ... */};
// or
const bar: TypeWithMandatoryAndOptionalProps = Object.assign(
{ numberProp: 1, boolProp: false },
{ blablabla: 'test' }
);
But both of those options basically tricks type checker rather than providing a sound type system for your program.
TL;DR of that would be as follows. Unless you're trying to get type working an existing JS program, just rethink your types. Use separate property for object with key signature or a Map
.
Thanks @jcalz for pointing to TS issue.
Upvotes: 1