I have the following object with an extended state object, I made an array of values that I want to check using a for of loop and check the state object's current value, issue is I cannot make the array value compatible with state object key, how to make them fit telling typescript that the value is a compatible key for the state object ?
const inicialState = {
a: true
b: true
c: false
d: true
e: true
};
const [type, setType] = useState < typeof inicialState > (inicialState);
const requirments = ['a', 'n', 'c'];
for (const value of requirments) {
if (!type[value] /* Cannot acces object key */ ) {
console.log('false')
}
}
CodePudding user response:
There's a number of ways you can solve this problem.
Your requirements
array is inferred as a string[]
, but what you want it to actually represent is "an array of the possible keys in inicialState
; you can use keyof
and typeof
to help here:
const requirments: (keyof typeof inicialState)[] = ['a', 'n', 'c'];
However, now you'll be warned that n
isn't a valid key (which it isn't!) - so you either need to give n
an initial value:
const inicialState: InicialState = {
a: true,
b: true,
c: false,
d: true,
e: true,
n: undefined,
};
Or better still, if your set of keys is fixed, then you should create a type / interface that describes the inicialState
:
interface InicialState {
a: boolean;
b: boolean;
c: boolean;
d: boolean;
e: boolean;
n?: boolean;
};
const inicialState: InicialState = {
// ...
};
const requirments: (keyof InicialState)[] = ['a', 'n', 'c'];
And if the set of keys is not fixed then you can use Record<string, boolean>
:
const inicialState: Record<string, boolean> = {
a: true,
b: true,
c: false,
d: true,
e: true,
};
CodePudding user response:
I guess the idea is that your requirements
array is dynamic (we cannot guarantee that everything in that array is a key of type
), so typescript is just warning you (or throwing error if you in strict mode) about that. A work around is to use Object.keys
to check if a string exists in an object key:
Update: at this point typescript still cannot infer that the value
here is a keyof
inicialState
so we just kinda have to help it a little bit
if (Object.keys(type).includes(value)) {
console.log(type[value as keyof typeof inicialState]);
}
Another way is to annotate the type
to be an object with that could have any string for it keys:
const inicialState: Record<string, boolean> = {
a: true,
b: true,
c: false,
d: true,
e: true
};
CodePudding user response:
type ObjectKey = keyof typeof type;
const requirments = ['a', 'b', 'c'] as ObjectKey[];
for (const value of requirments) {
if (!type[value]) {
console.log(false)
}
}