Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type definition in object literal in TypeScript

Tags:

typescript

In TypeScript classes it's possible to declare types for properties, for example:

class className {   property: string; }; 

How do declare the type of a property in an object literal?

I've tried the following code but it doesn't compile:

var obj = {   property: string; }; 

I'm getting the following error:

The name 'string' does not exist in the current scope

Am I doing something wrong or is this a bug?

like image 434
Dace Zarina Avatar asked Oct 08 '12 18:10

Dace Zarina


People also ask

What is the type for object in TypeScript?

In TypeScript, object is the type of all non-primitive values (primitive values are undefined , null , booleans, numbers, bigints, strings). With this type, we can't access any properties of a value.

What is type Definition TypeScript?

Built-in Type Definitions TypeScript includes declaration files for all of the standardized built-in APIs available in JavaScript runtimes. This includes things like methods and properties of built-in types like string or function , top-level names like Math and Object , and their associated types.

How do you declare a variable as a object in TypeScript?

The type syntax for declaring a variable in TypeScript is to include a colon (:) after the variable name, followed by its type. Just as in JavaScript, we use the var keyword to declare a variable. Declare its type and value in one statement.


2 Answers

You're pretty close, you just need to replace the = with a :. You can use an object type literal (see spec section 3.5.3) or an interface. Using an object type literal is close to what you have:

var obj: { property: string; } = { property: "foo" }; 

But you can also use an interface

interface MyObjLayout {     property: string; }  var obj: MyObjLayout = { property: "foo" }; 
like image 165
Brian Terlson Avatar answered Oct 10 '22 14:10

Brian Terlson


Update 2019-05-15 (Improved Code Pattern as Alternative)

After many years of using const and benefiting from more functional code, I would recommend against using the below in most cases. (When building objects, forcing the type system into a specific type instead of letting it infer types is often an indication that something is wrong).

Instead I would recommend using const variables as much as possible and then compose the object as the final step:

const id = GetId(); const hasStarted = true; ... const hasFinished = false; ... return {hasStarted, hasFinished, id}; 
  • This will properly type everything without any need for explicit typing.
  • There is no need to retype the field names.
  • This leads to the cleanest code from my experience.
  • This allows the compiler to provide more state verification (for example, if you return in multiple locations, the compiler will ensure the same type of object is always returned - which encourages you to declare the whole return value at each position - giving a perfectly clear intention of that value).

Addition 2020-02-26

If you do actually need a type that you can be lazily initialized: Mark it is a nullable union type (null or Type). The type system will prevent you from using it without first ensuring it has a value.

In tsconfig.json, make sure you enable strict null checks:

"strictNullChecks": true

Then use this pattern and allow the type system to protect you from accidental null/undefined access:

  const state = {     instance: null as null | ApiService,     // OR     // instance: undefined as undefined | ApiService,  };  const useApi = () => {     // If I try to use it here, the type system requires a safe way to access it      // Simple lazy-initialization      const api = state?.instance ?? (state.instance = new ApiService());     api.fun();      // Also here are some ways to only access it if it has value:      // The 'right' way: Typescript 3.7 required     state.instance?.fun();      // Or the old way: If you are stuck before Typescript 3.7     state.instance && state.instance.fun();      // Or the long winded way because the above just feels weird     if (state.instance) { state.instance.fun(); }      // Or the I came from C and can't check for nulls like they are booleans way     if (state.instance != null) { state.instance.fun(); }      // Or the I came from C and can't check for nulls like they are booleans      // AND I was told to always use triple === in javascript even with null checks way     if (state.instance !== null && state.instance !== undefined) { state.instance.fun(); } };  class ApiService {     fun() {         // Do something useful here     } } 

Do not do the below in 99% of cases:

Update 2016-02-10 - To Handle TSX (Thanks @Josh)

Use the as operator for TSX.

var obj = {     property: null as string }; 

A longer example:

var call = {     hasStarted: null as boolean,     hasFinished: null as boolean,     id: null as number, }; 

Original Answer

Use the cast operator to make this succinct (by casting null to the desired type).

var obj = {     property: <string> null }; 

A longer example:

var call = {     hasStarted: <boolean> null,     hasFinished: <boolean> null,     id: <number> null, }; 

This is much better than having two parts (one to declare types, the second to declare defaults):

var callVerbose: {     hasStarted: boolean;     hasFinished: boolean;     id: number; } = {     hasStarted: null,     hasFinished: null,     id: null, }; 
like image 21
Rick Love Avatar answered Oct 10 '22 13:10

Rick Love