DanielR
DanielR

Reputation: 596

Typescript - Force default type for additional properties in interface

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

Answers (1)

Kirill Dmitrenko
Kirill Dmitrenko

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

Related Questions