Type definition in object literal in TypeScript

后端 未结 9 2376
粉色の甜心
粉色の甜心 2020-11-27 09:29

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

class className {
  property: string;
};

How do declare

相关标签:
9条回答
  • 2020-11-27 09:42

    In your code:

    var obj = {
      myProp: string;
    };
    

    You are actually creating a object literal and assigning the variable string to the property myProp. Although very bad practice this would actually be valid TS code (don't use this!):

    var string = 'A string';
    
    var obj = {
      property: string
    };
    

    However, what you want is that the object literal is typed. This can be achieved in various ways:

    Interface:

    interface myObj {
        property: string;
    }
    
    var obj: myObj = { property: "My string" };
    

    Type alias:

    type myObjType = {
        property: string
    };
    
    var obj: myObjType = { property: "My string" };
    

    Object type literal:

    var obj: { property: string; } = { property: "Mystring" };
    
    0 讨论(0)
  • 2020-11-27 09:43

    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,
    };
    
    0 讨论(0)
  • 2020-11-27 09:44
    // Use ..
    
    const Per = {
      name: 'HAMZA',
      age: 20,
      coords: {
        tele: '09',
        lan: '190'
      },
      setAge(age: Number): void {
        this.age = age;
      },
      getAge(): Number {
        return age;
      }
    };
    const { age, name }: { age: Number; name: String } = Per;
    const {
      coords: { tele, lan }
    }: { coords: { tele: String; lan: String } } = Per;
    
    console.log(Per.getAge());
    
    0 讨论(0)
  • 2020-11-27 09:48

    I'm surprised that no-one's mentioned this but you could just create an interface called ObjectLiteral, that accepts key: value pairs of type string: any:

    interface ObjectLiteral {
      [key: string]: any;
    }
    

    Then you'd use it, like this:

    let data: ObjectLiteral = {
      hello: "world",
      goodbye: 1,
      // ...
    };
    

    An added bonus is that you can re-use this interface many times as you need, on as many objects you'd like.

    Good luck.

    0 讨论(0)
  • 2020-11-27 09:53

    If you're trying to write a type annotation, the syntax is:

    var x: { property: string; } = ...;
    

    If you're trying to write an object literal, the syntax is:

    var x = { property: 'hello' };
    

    Your code is trying to use a type name in a value position.

    0 讨论(0)
  • 2020-11-27 09:53

    If you're trying to add typings to a destructured object literal, for example in arguments to a function, the syntax is:

    function foo({ bar, baz }: { bar: boolean, baz: string }) {
      // ...
    }
    
    foo({ bar: true, baz: 'lorem ipsum' });
    
    0 讨论(0)
提交回复
热议问题