Reputation: 311
I need to define a type based on a config object (anObject
), which will be used in my code.
I wrote something like the following,
const anObject = {
foo: ["a", "b", "c"],
bar: ["d", "e", "f"],
} as const;
type aType =
| { key: ""; value: [] }
| { key: "foo"; value: ("a" | "b" | "c")[] }
| { key: "bar"; value: ("d" | "e" | "f")[] };
const a: aType = { key: "", value: [] }; // No error
const b: aType = { key: "foo"; value: ["a", "b"] }; // No error
const c: aType = { key: "bar"; value: ["e", "f"] }; // No error
How to declare aType
dynamically in TypeScript?
Upvotes: 2
Views: 1598
Reputation: 1404
What about this code?
const anObject = {
foo: ["a", "b", "c"],
bar: ["d", "e", "f"],
} as const;
type aType = {
key: keyof typeof anObject | "";
value: typeof anObject[keyof typeof anObject][number][];
} & (
| { key: ""; value: undefined[] }
| { key: "foo"; value: typeof anObject["foo"][number][] }
| { key: "bar"; value: typeof anObject["bar"][number][] }
);
const foo: aType = { key: "", value: [] };
I simply added the undefined type, so that I don't get an TypeScript error. Solves that your problem?
And the second problem is a simple implementation error, because if you base your type on the config object sure your type must have all properties of it. So you have to change your approach. If you can explain your needs more detailed I may be able to help you.
I know that this is very far-fetched now, but can it be that you wanted to something like this:
export interface MyConfiguration {
foo?: ("a" | "b" | "c")[],
bar?: ("d" | "e" | "f")[],
}
const DefaultMyConfiguration: MyConfiguration = {
foo: ["b", "c"],
bar: ["d"]
}
//In the middle of somewhere in your code you can now do this
let config: MyConfiguration
function myConstructor(config: MyConfiguration) {
config = {...DefaultMyConfiguration, ...config}
}
Upvotes: 0
Reputation: 33091
It worth using union here:
const anObject = {
foo: ["a", "b", "c"],
bar: ["d", "e", "f"],
} as const;
type AnObject = typeof anObject;
type Values<T> = T[keyof T]
type AType = {
[P in keyof AnObject]: {
key: P,
value: Array<AnObject[P][number]>
}
}
type Default = { key: ""; value: [] }
type Result = Values<AType> | Default
const foo: Result = { key: "", value: [] }; // ok
const bar: Result = { key: "bar", value: ["d"] } // ok
Feel free to add any new keys to anObject
. You don't need to make updates anywhere else
Please keep in mind, as @T.J Crowder said, there is no order in value
property.
TS will allow different combinations of value: [d,e] | [e, d] | [d]
.
If you want it in same order, just use this line: value: AnObject[P]
in AType
helper
Upvotes: 3