Skip to content

Speculation about #12596 Allow property (dotted) access syntax for types with string index signatures  #16027

Closed

Description

Continue discussion on #12596 Allow property (dotted) access syntax for types with string index signatures (introduced in TS 2.2).

Let's consider a component with options.

class MyComponent {
    static defaultOptions: MyComponent.Options = {
        presentation: "dropdown"
    };
    options: MyComponent.Options;
    constructor(options: MyComponent.Options) {
        this.options = utils.append(this.options, options, {deep: true});
    }
}
namespace MyComponent {
    export interface Options {
        presentation: "dropdown" | "inline";
    }
}

All options the component uses are declared in its interface.
So to create an instance:

let c = new MyComponenent({ presentation: "inline" });

Now, imagine that component accepts a callback:

    export interface Options {
        presentation: "dropdown" | "inline";
        onBeforeRender: () => void;
    }
let c = new MyComponenent({ 
    onBeforeRender: () => {
    }
});

Let's imagine that inside onBeforeRender we need access to some value passed from parent content.

let c = new MyComponenent(utils.append({ 
    onBeforeRender: () => {
        let val = this.options["theValue"];
    }
}, {
    theValue: theValueFromParent
});

So we're adding an aspect to class and it depends on some data provided by a different aspect.
The easiest way to implement something like this was to add index signature into Options:

namespace MyComponent {
    export interface Options {
        [key: string] => any;
    }
}

It allowed us to extend components without subclassing.
Now (since TS 2.2) it has very serious impact - we lost type checking for Options type at all. The worst thing is that it could be not very clear for people migrating from previous versions. Everything still works. No breaking changes. But accidentally one can notice then compiler doesn't help anymore:

class MyComponent {
    static defaultOptions: MyComponent.Options = {
        prisintetion: "dropdown" // should be error but it's not
    };
}

So, probably we have two different cases here: a type as map and a type with optional extensibility.

I'd suggest to introduce optional index signature which implements the previous behavior:

    export interface Options {
        [key: string]? => any;
    }

this would mean the same as before:

let opt: Options;
opt.noExisting;     // error
opt["noExisting"]; // ok
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    In DiscussionNot yet reached consensusSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions