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

Type annotation for object with unknown properties but known property types? #7803

Closed
remojansen opened this issue Apr 4, 2016 · 6 comments

Comments

@remojansen
Copy link
Contributor

I have encounter a few times in multiple applications an scenario in which I don't know the properties of an object but I do know that all its properties are of a certain type.

For example:

interface Metadata {
  key: string,
  value: any
}

var metadata = {
  someReducer: Metadata ,
  anotherReducer: Metadata , 
  // ...
}

In this scenario:

  • I don't know the property names or number of properties of metadata
  • I do know that Metadata is the type of all the properties of metadata

Now let's imagine that a function take the metadata object as argument:

function doSomething(metadata: any) {
  // ...
}

I used any as the type of the argument metadata but It would be great if I could let developers know that all the properties of this object must be of type Metadata.

is there any way to create such type annotation?

@s-panferov
Copy link

interface MetadataObj {
    [key: string]: Metadata
}
function doSomething(metadata: MetadataObj) {

or

type MetadataObj = {[key: string]: Metadata}
function doSomething(metadata: MetadataObj) {

or

function doSomething(metadata: {[key: string]: Metadata}) {

It is called index signature.

@remojansen
Copy link
Contributor Author

I'm just sharing in case it is useful for others...

The following doesn't work:

interface Metadata {
  key: string,
  value: any
}

interface MetadataObj {
    [key: string]: Metadata
}

// no explicitly typed!
var metadata = {
  someReducer: { key: "test", value: 1 } ,
  anotherReducer: { key: "test", value: 2 }
  // ...
};

function doSomething(metadata: MetadataObj) {
  // ...
}

doSomething(metadata);

The following works:

interface Metadata {
  key: string,
  value: any
}

interface MetadataObj {
    [key: string]: Metadata
}

var metadata : MetadataObj = { // type annotation here is needed
  someReducer: { key: "test", value: 1 } ,
  anotherReducer: { key: "test", value: 2 }
  // ...
};

function doSomething(metadata: MetadataObj) {
  // ...
}

doSomething(metadata);

@malibuzios
Copy link

Here's a simpler test case:

type Test = { [key: string]: { prop: number } };

let a: Test = { a: { prop: 1 } };  // <-- No error

let b = { a: { prop: 1 } };
let c: Test = b;                   // <-- Error in 1.8.9

This seems to be a bug that may have already been fixed. It errors in 1.8.9 but not on the nightly build.

@malibuzios
Copy link

I believe it was fixed by #7029 (Implicit index signatures). It should probably be included on the next release.

@remojansen
Copy link
Contributor Author

@malibuzios thanks for he details 😄

@karolmie1
Copy link

Just one question:
In this case: type Test = { [key: string]: { prop: number } };

Why do we have to name those variables? It is totally useless (if I'm wrong please enlighten me)
Wouldn't it be much better with only: type Test = { [string]: {number} };
This is pretty ok, but still few unnecessary characters: type Test = { [_: string]: { _: number } };

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants