Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Describing an Interface where unknown properties are of a specific type #20597

Closed
amarzavery opened this issue Dec 9, 2017 · 5 comments
Closed
Labels
Duplicate An existing issue was already created

Comments

@amarzavery
Copy link

amarzavery commented Dec 9, 2017

  • This is the json schema definition or a model defined in the OpenAPI specification 2.0.
{
  "Foo": {
    "properties": {
      "name": {
        "type": "string"
      },
      "age": {
        "type": "number"
      }
    },
    "additionalProperties": {
      "type": "string"
    }
  }
}

We would like to model an Interface in TS for the above json schema definition as follows:

interface Foo {
  name: string;
  age: number;
  [prop: string]: string;
}

However, TS gives the following error:

Property 'age' of type 'number' is not assignable to string index type 'string'.
  • Well, we can make the value of the indexed property a loose type any
interface Foo {
  name: string;
  age: number;
  [prop: string]: any; // but this defeats the purpose of providing good typing.
}

The above approach would be perfectly fine for "additionalProperties": true or "additionalProperties": { "type": "object" }, but not for specific types.

  • Another approach would be to make additionalProperties a Dictionary<string>.
interface Foo {
  name: string;
  age: number;
  additionalProperties: { [prop: string]: string}; 
}

This would be convenient for C#, Python, etc. developers (as they deal with objects in that language). However, it would be inconvenient for JS developers to provide (or access) a JSON object that has unknown properties in a property bag called additionalProperties.

Any help/idea in solving this problem will be very helpful.

@alexrock
Copy link

Intersection types allow this

type Foo =
  {
    name: string;
    age: number;
  } & {
    [prop: string]: string;
  };

@amarzavery
Copy link
Author

amarzavery commented Dec 10, 2017

@alexrock - Thanks for letting me know. Learnt something new today.

I tried the following

type Foo = {
  name: string;
  age: number;
} & {
  [prop: string]: string;
};

var f: Foo = {
  name: "foo",
  age: 10,
  color: "red"
};

and it still gives an error:

Type '{ name: string; age: number; color: string; }' is not assignable to type 'Foo'.
  Type '{ name: string; age: number; color: string; }' is not assignable to type '{ [prop: string]: string; }'.
    Property 'age' is incompatible with index signature.
      Type 'number' is not assignable to type 'string'.

NOTE: I also found some info at @basarat's TS gitbook which explains why all members must conform to the index signature.

@alexrock
Copy link

@amarzavery - I understand. Object literals don't allow this, but member access is still allowed and correctly typed.

type Foo =
  {
    name: string
    age: number
  } & {
    [prop: string]: string
  }

let foo: Foo = JSON.parse(`{
  "name": "foo",
  "age": 10,
  "color": "red"
}`)

foo.color = 0x0000ff // type error
foo.color = 'blue'   // ok, color is string

I can't say, absolutely, if this is the intended behavior.

@DanielRosenwasser
Copy link
Member

Looks like a potential duplicate of #17867 (partially discussed here #18394 (comment)).

@DanielRosenwasser DanielRosenwasser added the Duplicate An existing issue was already created label Dec 12, 2017
@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@microsoft microsoft locked and limited conversation to collaborators Jul 3, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants