TypeScript and dot-notation access to objects

前端 未结 5 406
半阙折子戏
半阙折子戏 2020-12-09 16:11

If TypeScript is a strict superset of JavaScript, why is dot notation on an arbitrary object erroneous? I have JS code that I want to convert over to TS for better type safe

相关标签:
5条回答
  • 2020-12-09 16:38

    I know you say this is odd, but this is one of the main reasons TypeScript exists. This error helps prevent accidentally setting or getting non-existent properties on an object.

    Right now, as the compiler is telling you, the property bar does not exist on x because it has been implicitly typed to {} when writing var x = {};.

    You can tell the compiler that x has more than zero properties by explicitly defining the type:

    var x: { foo?: string; bar?: string; } = {};
    

    Now you can get or set x.foo and x.bar without the compiler complaining. In most cases, you would move this into an interface like so:

    interface IFooBar {
        foo?: string;
        bar?: string;
    }
    
    var x: IFooBar = {};
    
    x.foo = "asdf";  // ok
    x.test = "asdf"; // error, as it should be
    

    Some people are recommending you cast to any, but don't get lazy. You should make full use of the type system TypeScript provides. Doing so will most definitely save you time down the road as you maintain an application.

    0 讨论(0)
  • 2020-12-09 16:54

    mwilson got there before I could! ;)

    In the code above, Typescript is unable to determine that the object x exposes a property called bar so cannot resolve it when displaying Intellisense.

    Instead, add foo, bar, etc. as properties of the object itself:

    var x = {
        foo: "FOO",
        bar: "BAR"
    };
    

    Then, when using the Typescript Playground, you'll be see the Intellisense work as expected:

    enter image description here

    HTH

    0 讨论(0)
  • 2020-12-09 16:55

    Because of the strongly-typed nature of Typescript Object, you can use "any" to make it untyped:

    var x: any = {};
    x.bar = "bar";   /// ok
    

    If what's you need is to define type of literal properties

    var x: { [index: string]: TypeA } = {};
    

    then x["bar"] can now only be instance of TypeA.

    0 讨论(0)
  • 2020-12-09 17:00

    I personally prefer to specify types whenever I have the chance.

    Note, that you can only instantiate this variable with {} if you define the fields as optional with the ?: operator.

    let x: {foo?: string, bar?: string} = {};
    x.foo = 'foo';
    x.bar = 'bar';
    

    As others have said, if you plan to use this type multiple times, it's probably better to make an explicit class for it.

    PS: it's better to use let instead of var when programming in typescript. (e.g. the scope of a var declaration is a bit quirky, compared to a let which does what you expect it to do.)

    0 讨论(0)
  • 2020-12-09 17:02

    x does not hold any property named bar so you need create it within the object:

    function foobar() {
        var x = {
    
            foo: 'foo',
            bar: 'bar'
        }
    
        return x;
    }
    
    alert(foobar().bar); //returns bar
    
    0 讨论(0)
提交回复
热议问题