ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Advanced Object Types
    TypeScript 2023. 8. 9. 16:58

    타입스크립트의 Advanced Object Types에 대해 정리하였습니다.

     

     


    < Introduction >

    One of the challenges of writing TypeScript is knowing how to apply types in every situation we’ll encounter within our code.

    This lesson is about how we can deal with a variety of situations to make sure that our code is typed with object-oriented programming patterns, no matter what our program does or how it's structured. Types should always help make our code safer, without imposing restrictions on how we write and organize our code.

     

     


    Interfaces and Types >

    In TypeScript, we can define types in a variety of ways to fit our code. We’ve used the type keyword to define types, however, there’s another way to define types with the interface keyword.

     

    Example)

    // type
    type Mail = {
      postagePrice: number;
      address: string;
    }
     
    const catalog: Mail = ...
    
    // interface
    interface Mail {
      postagePrice: number;
      address: string;
    }
     
    const catalog: Mail = ...

    The biggest difference between interface and type is that interface can only be used to type  objects , while type can be used to type  objects  primitives , and more.

     

    =>  So why would we use interface?
    : Sometimes, we don’t want a type that can do everything. We’d like our types to be constrained so we’re more likely to write consistent code.
    Since interface may only type objects, it’s a perfect match for writing object-oriented programs because these programs need many typed objects.

     

     


    Interfaces and Classes >

    The interface keyword in TypeScript is especially good for adding types to a class. Since interface is constrained to typed objects and using class is a way to program with objects, interface and class are a great match.

    TypeScript gives us the ability to apply a type to an object/class with the implements keyword.

     

    Example)

    interface Robot {
      identify: (id: number) => void;
    }
     
    class OneSeries implements Robot {
      identify(id: number) {
        console.log(`beep! I'm ${id.toFixed(2)}.`);
      }
     
      answerQuestion() {
        console.log('42!');
      }
    }

    The implements keyword is then used to apply the type  Robot  to OneSeries.

    Since  Robot  is applied to OneSeriesOneSeries must include a method named .identify( ) that matches the  Robot  interface. Additionally, OneSeries can have methods and properties of its own, like the .answerQuestion() method.

     

     


    Deep Types >

    TypeScript allows us to infinitely nest objects so that we can describe data correctly.

     

    Example)

    class OneSeries implements Robot {
      about;
     
      constructor(props: { general: { id: number; name: string; } }) {
        this.about = props;
      }
     
      getRobotId() {
        return `ID: ${this.about.general.id}`;
      }
    }

    In this classOneSeries expects to have an about property that is an object with a nested object inside it. Inside getRobotId( )OneSeries returns this.about.general.id. To type an object nested inside another object, we could write an interface like this:

    interface Robot {
      about: {
        general: {
          id: number;
          name: string;
        };
      };
      getRobotId: () => string;
    }

     

     


    Composed Types >

    As our data gets nested deeper, we’ll start to have typed objects that become unwieldy to write and read.

     

    Bad Example)

    interface About {
      general: {
        id: number;
        name: string;
        version: {
          versionNumber: number;
        }
      }
    }
    1. As we add more data, this interface may become so nested it’s hard for ourselves and other developers to read.
    2. It’s likely that we may want just a nested part of this type somewhere. For instance, we may want just the  version  object type in our program, and it would be nice if we could use it without all the other type members in  About .

     

    Good Example)

    interface About {
      general: General;
    }
     
    interface General {
      id: number;
      name: string;
      version: Version;
    }
     
    interface Version {
      versionNumber: number;
    }

    The resulting code is a little longer, but we addressed the problems with a big interface: we can now read our code easier with named types and we can reuse the smaller interfaces in other places in our code.

     

     


    Extending Interfaces >

     it’s not always enough to be able to compose types together. Sometimes it’s convenient to copy all the type members from one type into another type. We can accomplish this with the extends keyword.

     

    Example)

    interface Shape {
      color: string;
    }
     
    interface Square extends Shape {
      sideLength: number;
    }
     
    const mySquare: Square = { sideLength: 10, color: 'blue' };

     

     


    Index Signatures >

    Sometimes it's not possible to know the property names for an object.
    In that case, it’s useful to write an object type that allows us to include a variable name for the property name. This feature is called index signatures

     

    Example: Imagine we query a map API to get a list of latitudes where a solar eclipse can be viewed

    {
      '40.712776': true;
      '41.203323': true;
      '40.417286': false;
    }

    : We know that all the property names will be strings, and all their values will be booleans, but we don’t know what the property names will be.

    => To type this object, we can utilize an index signature to type this object.

    interface SolarEclipse {
      [latitude: string]: boolean;
    }

    : The [latitude: string] syntax defines every property name within SolarEclipse as a string type with a value of type boolean.

     

     


    Optional Type Members >

    TypeScript allows us to make some type members optional in interface.

     

    Example)

    interface OptionsType {
      name: string;
      size?: string;
    }
     
    function listFile(options: OptionsType) {
      let fileName = options.name;
     
      if (options.size) {
        fileName = `${fileName}: ${options.size}`;
      }
     
      return fileName;
    }

    : size property is optional

     

     

     

     

     

     

     

     

    'TypeScript' 카테고리의 다른 글

    Type Narrowing  (0) 2023.07.24
    Union Types  (0) 2023.07.07
    Custom Types  (0) 2023.06.19
    Array  (0) 2023.06.06
    Functions  (0) 2023.05.25

    댓글

Designed by Tistory.