3

I'm trying to write a d.ts file for an API which has a collection object representing an ordered collection of key-value pairs. The keys and values are all strings. Thus, the behavior is:

  • thing["foo"] returns the string value of the pair where key is "foo"
  • thing[1] returns the string value of the second pair in the ordered collection
  • thing.length returns the count of key-value pairs as a number

I tried the following, but it produced the error "An index signature parameter must be type 'string' or 'number':

declare class FrobCollection {
    [index: string|number] : string;

}

Is there a way to model the behavior of this object correctly in TypeScript?

EDIT: I found a way to model the two indexers, but still can't get the length property to work.

2 Answers 2

5
  • thing["foo"] returns the string value of the pair where key is "foo"
  • thing[1] returns the string value of the second pair in the ordered collection
  • thing.length returns the count of key-value pairs as a number

The problem is that the first bullet is not true for all values of "foo". For example, thing["0"] is a string, but thing["length"] is a number, and for an arbitrary string x you can't actually predict the type of thing[x]

The accurate definition for this type is:

declare class HeaderCollection {
    length: number;
    [index: number]: string;
    [key: string]: number|string;
}

where it's up to the caller to ensure that they actually indexed by a value that didn't match up with some reserved name like length, or a string that was actually a number.

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

1 Comment

You're absolutely right. It's unfortunate the library implemented this the way they did; it's going to make declaring any function signatures on this type very difficult.
0

I found a way that appears to work, though I haven't been able to test it fully yet.

declare class HeaderCollection {
    [index: number] : string;
    [key: string] : string;
}

I thought this would complain because TypeScript normally doesn't allow overloading, but it appears that's not the case this time. However, I'm still unable to declare the length property of type number, so I'm not out of the woods yet.

Comments

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.