Object.keys
always return string[]
, no matter what. Of course, it is expected that it returns Array<keyof typeof obj>
in this case, but it is not true.
Please see this list of issues on github.
First thing that should be done in this case is type assertion
.
(Object.keys(obj) as Array<keyof typeof obj>)
However, this is not the end.
There is still an error here:
this[key] = obj[key]; // error
In general, TS does not like mutations. Please see my article and this answer.
Type of this[key]
and obj[key]
is string | boolean
.
Please see this code:
type Key = "name" | "check";
let _name: Key = 'name'
let _check: Key = 'check'
obj[_name] = obj[_check] // error
Above code is almost equal to yours, except, your mutation is inside of iterator and mine is not. There is no binding between iteration index and type of key
.
See example:
(Object.keys(obj) as Array<keyof typeof obj>)
.forEach((key, index) => {
if (index === 0) {
const test = key // keyof modal and not "name"
}
})
It is correct behavior, because even JS specification does not give you a guarantee that first key
is name
. JS engine reserves the right to return you keys in any order. Sure, in 99.99% cases you will get the expected order, but it does not mean that you have a guarantee.
So, why do we have never
in the error message ? TypeScript makes an intersection of expected keys (of union) because it is safer to get common type. Intersection of string & boolean
- gives you never
, this is why you have this error message.
I believe the best you can do without using type assertions
is to call reduce
:
interface modal {
name: string;
check: boolean;
}
type Key = "name" | "check";
const obj: modal = fn();
function fn(): any {
return {
name: "hello"
}
}
class Modal implements modal {
name: string;
check: boolean;
constructor() {
this.name = "";
this.check = false;
const result = (Object.keys(obj) as Array<keyof typeof obj>)
.reduce((acc, key) => ({
...acc,
[key]: obj[key]
}), this)
Object.assign(this, result)
}
}
Playground
It worth using implements modal
or capitalize modal
interface.