2

I want to be able to pass interface into a certain function in typescript, where that function can accept any object type, so long as all of its properties are of a certain type.

Consider the following example:

function DoSomething(args: { readonly [propertyName: string]: string }) {
    // do something
}

// MyArgs is really just a more strongly typed version of {[propertyName: string]: string}
interface MyArgs {
    foo: string;
    bar: string;
}

var someArgs: MyArgs = {
    foo: "foo",
    bar: "bar"
}

DoSomething({ foo: "foo", bar: "bar" }); // works
DoSomething(someArgs); // compile error: Index signature is missing in type 'MyArgs'

This doesn't work because someArgs can not be cast to the parameter type used for the function's argument.

This is different from Typescript: Index signature is missing in type because of the readonly modifier which means that the DoSomething function cannot add new propertly to args. This means that an instance of MyArgs will still comply with this interface signature after DoSomething has been invoked against it.

How can I represent this in Typescript? Is there another way of doing this that I am missing?

3
  • Possible duplicate of Typescript: Index signature is missing in type Commented Sep 5, 2018 at 5:19
  • It is related but I think it is different. Note the readonly modifier which means that the DoSomething function cannot add new propertly to args, which means that an instance of MyArgs will still comply with this signature after DoSomething has been invoked against it. Commented Sep 5, 2018 at 5:23
  • After removing readonly does typescript compile it? I don't think readonly or not does not make any difference here at all. Commented Sep 5, 2018 at 16:06

1 Answer 1

5

An object literal type is assignable to a type with an index signature if the property types are compatible, but an interface type is not; see this comment. Once you annotate someArgs as type MyArgs, the information that it was an object literal is lost and only the MyArgs type is used for checking assignability to the parameter type of DoSomething. The readonly modifier is irrelevant: the question is whether someArgs satisfies TypeScript's (very imperfect) heuristic for being unlikely to have had non-string properties added before it is passed to DoSomething.

To make the example work, you can just change MyArgs to an object literal type:

type MyArgs = {
    foo: string;
    bar: string;
};
Sign up to request clarification or add additional context in comments.

1 Comment

Ah of course. The bit of insight I was lacking was that interfaces can be augmented. Thanks :)

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.