2

I really need to be able to check dynamically if aa is a property of my complex object called validations

const check = 'propertya' + 'a'; // result of a complex calculation that returns string 'propertyaa'

validations= {
    'a' : {
      'propertyaa': 'ax',
      'ab': 'ay',
      'ac': 'az'
    },
    'b' : {
      'ba': 'ax',
      'bb': 'ay',
      'bc': 'az'
    }
  };

if (this.validations.a[check] === undefined) {  ...

Error is:

element implicitly has an any type because type '{ ' propertyaa': string, 'ab': string, 'ac': string; }' has no index signature
(property) 'a': {
    'propertyaa': string;
    'ab': string;
    'ac': string;
}

Curiously the static (not dynamic) variant works if (this.validations.a['ab']) {

4
  • Both tests are working fine for me... Commented May 2, 2018 at 14:30
  • 3
    This bit gives you the error: this.validations.a[check]? I can't reproduce this. Commented May 2, 2018 at 14:30
  • 1
    My test working well. Commented May 2, 2018 at 14:30
  • Yes that bit: this.validations.a[check] gives the error Commented May 2, 2018 at 15:21

3 Answers 3

1

You can go one of two routes. You can either add an index signature to your validation properties:

type Indexable = { [name: string]: string }
const validations = {
    'a': {
        'propertyaa': 'ax',
        'ab': 'ay',
        'ac': 'az'
    } as Indexable,
    'b': {
        'ba': 'ax',
        'bb': 'ay',
        'bc': 'az'
    } as Indexable
};

const check = 'propertya' + 'a';
if (validations.a[check] === undefined) {
}

You could also just cast the property to Indexable when you use it:

if ((validations.a as Indexable)[check] === undefined) {
}

You could also use any instead of Indexable, but the Indexable defined above provides more type safety then any

Another option is to assert that the string check is in fact a key for the value of a:

if (validations.a[check as 'propertyaa'] === undefined) {
}

Edit

If you go with the first option, a helper function can help avoid the need for the type assertion on each property of validations:

type Indexable = { [name: string]: string }
const validations = createValidations({
    'a': {
        'propertyaa': 'ax',
        'ab': '19',
        'ac': 'az'
    },
    'b': {
        'ba': 'ax',
        'bb': 'ay',
        'bc': 'az'
    }
});
function createValidations<T>(o: { [P in keyof T]: T[P] & Indexable}) : typeof o {
    return o;
}
const check = 'propertya' + 'a';
if (validations.a[check] === undefined) {
}
Sign up to request clarification or add additional context in comments.

Comments

0

You will need index signature...

interface ComplexObject {
    [index: string ]: string | ComplexObject;
}

const check = 'propertya' + 'a';

const validations: ComplexObject = {
    'a' : {
      'propertyaa': 'ax',
      'ab': 'ay',
      'ac': 'az'
    },
    'b' : {
      'ba': 'ax',
      'bb': 'ay',
      'bc': 'az'
    }
  };

if (this.validations.a[check] === undefined) {
    // ...
}

1 Comment

Sorry but I get: Element explicitly has an any type because type string | ComplexObject has no index signature. Am i missing something? thank u! Now i get this even if i check for this.validations.a['propertyaa']
0

There is a simpler solution and really the only one that works for me so far:

cartoons = {
      'producers': {
          'Disney': 'Walt Disney',
          'PIXAR1': 'John John'
       }
    }

const check = 'Dis' + 'ney';
    const y = (<any>this.cartoons.producers)[check]; // notice the cast to any
    alert(y);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.