简体   繁体   中英

Access object in Typescript/Javascript

class ResistorColor {
  private colors: string[]
    
  public colorValues = {
    black: 0,
    brown: 1,
    red: 2,
    orange: 3,
    yellow: 4,
    green: 5,
    blue: 6,
    violet: 7,
    grey: 8,
    white: 9
  }

  constructor(colors: string[]) {
    
    if( colors.length > 2)
    {
      for( key in this.colorValues)
      {
        if (this.colorValues[key].indexOf(colors[0]) !== -1) 
        {
          return key;
        }
      }
    }

    this.colors = colors
    
  }
}

Idea is to find whether the color that has been input by the user is present in the object colorValues or not.

I referred to this: Find a value in a JavaScript object

I am getting the error of cannot find name key . I am using a Typescript, online editor.

Please explain to me what am I doing wrong here.

Look at @Owl 's answer, it fixes the other problems in your code too.

In your loop the variable key is not defined. You'd have to write it like this:

for (const key in this.colorValues) {
  ...
}

Although I wouldn't use a for-in loop, since objects have their own prototype properties, which you would also receive in a for-in loop. A better solution would be this:

for (const key of Object.keys(this.colorValues) {
  ...
}

But since you don't need the keys and just use them to retreive the values in the colorValues object, you could also use this:

for (const color of Object.values(this.colorValues) {
  ...
}

The cannot find name key error is answered by @MrCodingB

A nicer way to write this:

class ResistorColor {
  private colors: string[]
    
  public colorValues = {
    black: 0,
    brown: 1,
    red: 2,
    orange: 3,
    yellow: 4,
    green: 5,
    blue: 6,
    violet: 7,
    grey: 8,
    white: 9
  }

  constructor(colors: string[]) {
    
    const colorValues = Object.keys(this.colorValues);
    // colorValues is ["black", "brown", "red", ...]

    const isValid = colors.every(c => colorValues.includes(c));
    // `every` is used to tests whether all elements in the array pass the test implemented by the provided function, 
    // in this case, we check whether each value exists in `colorValues`

    if (isValid) {
      this.colors = colors
    } else {
      throw new Error("Invalid Color(s)");
    }
  }
}

const resistorColor = new ResistorColor(["black", "brown"]); // correct
console.log("resistorColor has correct color");

const resistorColor2 = new ResistorColor(["black", "brown", "gold"]); // throws error
console.log("resistorColor2 has correct color");

Typescript playground


It's also possible to print out the incorrect colors value by using .filter()

class ResistorColor {
  private colors: string[]
    
  public colorValues = {
    black: 0,
    brown: 1,
    red: 2,
    orange: 3,
    yellow: 4,
    green: 5,
    blue: 6,
    violet: 7,
    grey: 8,
    white: 9
  }

  constructor(colors: string[]) {
    
    const colorValues = Object.keys(this.colorValues);
    const invalidColors = colors.filter(c => !colorValues.includes(c));

    if (invalidColors.length === 0) {
      this.colors = colors
    } else {
      throw new Error(`Invalid Color -> ${invalidColors.join(", ")}`);
    }
  }
}

const resistorColor = new ResistorColor(["black", "brown"]); // correct
console.log("resistorColor has correct color");

const resistorColor2 = new ResistorColor(["black", "brown", "gold", "foo"]); // throws error "Invalid Color -> gold, foo"

Typescript playground

Some of the errors that you are trying to prevent at run-time can be avoided at compile-time with stricter types. You can create a type that only allows specific string literal color names and you can also enforce a minimum length on the colors array using tuple types .

It looks like this.colorValues might just be an enum ?

enum COLOR_VALUES {
    black = 0,
    brown = 1,
    red = 2,
    orange = 3,
    yellow = 4,
    green = 5,
    blue = 6,
    violet = 7,
    grey = 8,
    white = 9
}

type ColorNames = keyof typeof COLOR_VALUES;

class ResistorColor {

    // can have two or more colors
    constructor(private colors: [ColorNames, ColorNames, ...ColorNames[]]) {
    }
}

Now you can only call the constructor with valid arguments.

const a = new ResistorColor(["black", "blue"]); // ok
const b = new ResistorColor(["black", "blue", "red"]); // ok
const c = new ResistorColor(["black"]); // error: Source has 1 element(s) but target requires 2.
const d = new ResistorColor(["white", "cyan"]); // error: Type '"cyan"' is not assignable to type 

Typescript Playground Link

If this.colorValues is an instance variable I would create the initial value outside of the class so that we can use typeof .

const initialValues = {
    black: 0,
    brown: 1,
    red: 2,
    orange: 3,
    yellow: 4,
    green: 5,
    blue: 6,
    violet: 7,
    grey: 8,
    white: 9
  }

type ColorNames = keyof typeof initialValues;

class ResistorColor {

    public colorValues = initialValues;

    // can have two or more colors
    constructor(private colors: [ColorNames, ColorNames, ...ColorNames[]]) {
    }
}

Typescript Playground Link

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM