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
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.
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:
HTH
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.
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.)
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