0

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?

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

No, this still produces an error: Property 'numberProp' is incompatible with index signature. Type 'number' is not assignable to type 'string'.
I've checked the code with TS playground. Where have you put index signature? Note that the interface does not have it. Also what version of TS are you using?
I suspect @DanielR is having a problem like this: const foo2: TypeWithMandatoryAndOptionalProps = { boolProp: true, numberProp: 3 }. There is an open issue surrounding this problem, so maybe @KirillDmitrenko can mention this in the answer.
@jcalz Yep, looks like it. Thanks for the issue link, updated the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.