GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Implicit index signatures by ahejlsberg · Pull Request #7029 · microsoft/TypeScript

Conversation

@ahejlsberg

@ahejlsberg Anders Hejlsberg (ahejlsberg) commented Feb 11, 2016

Copy link
Copy Markdown
Member

Fixes #6041.

With this PR an object literal type is assignable to a type with an index signature if all known properties in the object literal are assignable to that index signature. This makes it possible to pass a variable that was initialized with an object literal as parameter to a function that expects a map or dictionary:

function httpService(path: string, headers: { [x: string]: string }) { }

const headers = {
    "Content-Type": "application/x-www-form-urlencoded"
};

httpService("", { "Content-Type": "application/x-www-form-urlencoded" });  // Ok
httpService("", headers);  // Now ok, previously wasn't

The PR adds the following three assignment compatibility rules (where an object literal type is the inferred type of an object literal or a type declared using an object type literal with no call or construct signatures):

  • An object literal type S with no index signatures is assignable to a type T with a string index signature M if each property in S is of a type that is assignable to the type of M.
  • An object literal type S with no index signatures is assignable to a type T with a numeric index signature M if each numerically named property in S is of a type that is assignable to the type of M.
  • An object literal type S with no string index signature and a numeric index signature N is assignable to a type T with a string index signature M if the type of N is assignable to the type of M and each property in S is of a type that is assignable to the type of M.

The PR adds corresponding type inference rules.

The PR furthermore removes the rule that adds index signatures to an object literal when it is contextually typed by a type that has index signatures. Instead, the type inferred for an object literal has index signatures only if it contains computed properties. For example:

let s = "hello";
let n = 123;
let o = {
    [s]: new Date(),
    [n]: new Error()
};

In the above, the type of o is { [x: string]: Date | Error, [x: number]: Error }.

Removing the automatic contextual index signatures from object literal types has the nice effect of reducing noise in our error messages. Also, we can now report the name of the offending property when an object literal doesn't meet the constraint implied by a target index signature (previously you'd have to deduce it yourself from two incompatible union types).

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

niieani, guncha, elisee, alitaheri, ejsmith, pinyin, HerringtonDarkholme, basarat, Hotell, ulrichb, and 8 more reacted with thumbs up emoji mquandalle, smikitky, tp, Meowtimer, Hotell, snipervld, and dartzki reacted with hooray emoji mquandalle, alitaheri, basarat, sebald, snipervld, and ythecombinator reacted with heart emoji
All reactions
  • 👍 18 reactions
  • 🎉 7 reactions
  • ❤️ 6 reactions
Anders Hejlsberg (ahejlsberg) added 9 commits February 9, 2016 14:31
@ahejlsberg
Implicit index signatures for object literal types
1d428b9
@ahejlsberg
Accepting new baselines
837e6db
@ahejlsberg
Include index signatures in object literal types only when computed p…
040effd
…roperties are present
@ahejlsberg
Accepting new baselines
d9fc61b
@ahejlsberg
Adding test
bb7ba1d
@ahejlsberg
Simplify indexTypesRelatedTo function
5f95c75
@ahejlsberg
Infer index signatures when object literals contain computed properties
b724a09
@ahejlsberg
Accepting new baselines
678d591
@ahejlsberg
Removing unused function
1af4e1c
@msftclas Microsoft Contribution License Agreements (msftclas) added the cla-not-required label Feb 11, 2016
RyanCavanaugh
RyanCavanaugh reviewed Feb 11, 2016
View reviewed changes
Comment thread src/compiler/checker.ts
}

/**
* Return true if type was inferred from an object literal or written as an object type literal

@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) Feb 11, 2016

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... " with no call/construct signatures"

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@RyanCavanaugh

Ryan Cavanaugh (RyanCavanaugh) commented Feb 11, 2016

Copy link
Copy Markdown
Member

👍

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

1 similar comment
@sandersn

Nathan Shively-Sanders (sandersn) commented Feb 11, 2016

Copy link
Copy Markdown
Member

👍

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ahejlsberg
Fixing comment
a1040f0
DanielRosenwasser
DanielRosenwasser reviewed Feb 12, 2016
View reviewed changes
Comment thread tests/baselines/reference/contextualTypeAny.errors.txt
@@ -0,0 +1,15 @@
tests/cases/compiler/contextualTypeAny.ts(3,5): error TS2322: Type '{ p: string; q: any; }' is not assignable to type '{ [s: string]: number; }'.
Property 'p' is incompatible with index signature.

@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) Feb 12, 2016

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you not report the index signature here? This is probably confusing for users, especially if the index signature type ever gets cut out.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@ahejlsberg Anders Hejlsberg (ahejlsberg) Feb 12, 2016

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dunno. I think it is pretty decent the way it is now and the last line makes it completely clear what isn't compatible with what.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) Feb 12, 2016

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear what the type of p is without the full type, so it'd be better to just report the index signature given that it'd take relatively little effort on our part.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) Feb 12, 2016

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I don't see how it would be better if we didn't show the index signature

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@ahejlsberg Anders Hejlsberg (ahejlsberg) Feb 12, 2016

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but the whole point of our elaboration scheme is to not try to show everything on one line. The respective types of p and the index signature follow in the next elaboration. It's completely analogous to how we report a mismatch between two properties.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) mentioned this pull request Feb 12, 2016
Design Meeting Notes, 2/12/2016 #7059
Closed
Anders Hejlsberg (ahejlsberg) added a commit that referenced this pull request Feb 16, 2016
@ahejlsberg
Merge pull request #7029 from Microsoft/implicitIndexSignatures
a8633ee
Implicit index signatures
@ahejlsberg
Anders Hejlsberg (ahejlsberg) merged commit a8633ee into master Feb 16, 2016
@ahejlsberg
Anders Hejlsberg (ahejlsberg) deleted the implicitIndexSignatures branch February 16, 2016 23:37
@RyanCavanaugh

Ryan Cavanaugh (RyanCavanaugh) commented Feb 17, 2016

Copy link
Copy Markdown
Member

Sad that I'm not going to rake in 30-100 Stack Overflow rep every week for my answer on this one anymore.

billba, svieira, niieani, and uilyam reacted with heart emoji
All reactions
  • ❤️ 4 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@MrHen

MrHen commented Feb 17, 2016

Copy link
Copy Markdown

Ryan Cavanaugh (@RyanCavanaugh) Heh.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) mentioned this pull request Feb 17, 2016
Optional index signature #7118
Closed
@jcristovao João Cristóvão (jcristovao) mentioned this pull request Feb 23, 2016
limited use of [index:string] typed-typings/npm-ramda#10
Closed
@tinganho

Tingan Ho (tinganho) commented Feb 25, 2016

Copy link
Copy Markdown
Contributor

I just tried this out. Shouldn't a type parameter inherit the index signature?

I have the following class:

export abstract class Component<P, T extends { [index: string]: string }, E extends { [element: string]: DOMElement }> extends EventEmitter {

And I was hoping I could just write:

export abstract class MyComponent<P, T, E> extends Component<P, T, E> {

And it would just inherit the index signature. But instead I need to explicitly write the constrained index signature. Which is quite painful, since I have many subclasses of Component.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@tinganho

Tingan Ho (tinganho) commented Feb 25, 2016

Copy link
Copy Markdown
Contributor

Ok seems like this PR doesn't work for type arguments? Just passing a type, as a type argument, with all members satisfying the index signature doesn't work for me.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@glatzert Thomas Ottenhus (glatzert) mentioned this pull request Feb 25, 2016
[react] Updated interface HTMLAttributes DefinitelyTyped/DefinitelyTyped#8236
Merged
@JabX

Damien Frikha (JabX) commented Feb 26, 2016

Copy link
Copy Markdown

I would also love to have what Tingan Ho (@tinganho) wants.

My use case is the following:

interface ITest {
    [x: string]: string
}

class Test<T extends ITest> {
    content: T
}

const myObject = {
    test: "hello"
};

class MyTest extends Test<typeof myObject> {
    // Error, 'typeof myObject' doesn't implement the index signature...
    method() {
        console.log(this.content.test)
    }
}

I'm planning to do this extensively with model-generated object litterals (like myObject here) and it'd be nice not to have to also generate the corresponding interface for all those litterals... it could work out though, so I guess it's not that big of an issue.

If you want to keep forcing the index signature to be respecified in a derived interface, maybe then my issue could be fixed by typeof infering an index signature if applicable, if that's not too stupid of an idea.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Michał Miszczyszyn (typeofweb) referenced this pull request in DefinitelyTyped/DefinitelyTyped Mar 22, 2016
@typeofweb
Update AngularJS to 1.5
65347ef
@malibuzios malibuzios mentioned this pull request Apr 5, 2016
Type annotation for object with unknown properties but known property types? #7803
Closed
@JabX Damien Frikha (JabX) mentioned this pull request Sep 15, 2016
Omit index signature with generic type constraints? #10941
Closed
@ahejlsberg Anders Hejlsberg (ahejlsberg) mentioned this pull request Mar 19, 2017
assignabiltity between interfaces and types #14736
Closed
@wclr

Alex (wclr) commented Mar 20, 2017

Copy link
Copy Markdown

Asked this in #14736

Why this case:

function httpService(path: string, headers: { [x: string]: string }) { }

interface MyHeaders {
  'Content-Type': string
}

const headers: MyHeaders = {
    "Content-Type": "application/x-www-form-urlencoded"
};

httpService("", { "Content-Type": "application/x-www-form-urlencoded" });  // Ok
httpService("", headers);  // NOT OK

is NOT valid, the error is:

Argument of type 'MyHeaders' is not assignable to parameter of type '{ [x: string]: string; }'.
  Index signature is missing in type 'MyHeaders'.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) mentioned this pull request Aug 18, 2017
index operator and object spread #17849
Closed
@microsoft 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.

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

9 participants

@ahejlsberg @RyanCavanaugh @sandersn @MrHen @tinganho @JabX @wclr @DanielRosenwasser @msftclas
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.