this code won't compile:
interface IFoo {
a: number;
}
type TFoo = keyof IFoo;
type OFoo = { [key: TFoo]: any };
let obj: OFoo = { a: 1 };
What I'm trying to achieve is for obj to only be assignable with object with valid properties, as if I wrote:
let obj: IFoo = { a: 1};
but I need to do it by keyof.
Thanks for any ideas.
While you can't directly use anything but string
or number
as the key type in an index signature (and your definition of OFoo
will give you an error to that effect), you can restrict keys to a subtype of string
using mapped types. Since TFoo
, a.k.a. keyof Foo
, is a subtype of string
, you can use a mapped type like this:
type OFoo = { [K in TFoo]: any };
Note that the syntax for mapped types differs from that of regular index signatures. The TFoo
above corresponds to the type of allowable keys, which is just "a"
in your case, but could also be a union of string literals like "a"|"b"|"c"
, or even string
. And the K
above is a parameter which corresponds to the type of key for each property. (You don't really care about K
since the type for each property value is any
and has nothing to do with K
, but you could have used K
to pick out particular properties if you wanted to.) Anyway, let's use it:
let obj: OFoo = { a: 1 }; // okay
let obj = { }; // error, property 'a' is missing
let obj = { c: 1 }; // error, excess property 'c'
By the way, I'd probably use the built-in standard library type Record<K,T>
which is defined like this:
type Record<K extends string, T> = {
[P in K]: T
}
Or, you can think: "a Record<K, T>
is an object where every key is in K
and every value is a T
". And for you, K
is TFoo
, and T
is any
:
type OFoo = Record<TFoo, any>; // same thing
Hope that helps; good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With