0
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.

2
  • 1
    Not related to the question, instead of a.indexOf(v) !== -1 use a.includes(v). Commented Mar 23, 2021 at 8:53
  • @axiac Thank you. I will upvote if you write that as an answer. Commented Mar 23, 2021 at 14:11

3 Answers 3

3

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) {
  ...
}
Sign up to request clarification or add additional context in comments.

2 Comments

alright. Is there any other way of writing it?
Edited my answer
2

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

1 Comment

Thank you for the detailed answer.
1

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

1 Comment

Very much thankful for the helpful answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.