'Is Typescript able to force the domain of a value to be within a set of key names declared in the same object?
I am quite new to Typescript and I am really appreciating its type checking capabilities.
I need to understand if with its capabilities it is possible to check at compile time if the domain of a value is within a set of key names declared in the same object?
The following example will help to clarify my question. I have these object and type definitions:
type ElemField = { name: string }
type Elem = Record<string, ElemField>
type Relation = { path: string[] }
type MySchema = {
elem: Record<string, Elem>,
relations: Record<string, Relation>
}
const test: MySchema = {
elem: {
elem1: {
prop1: { name: 'string' },
},
elem2: {
prop2: { name: 'string' },
prop3: { name: 'string' },
},
elem3: {
prop4: { name: 'string' },
}
},
relations: {
relation1: {
path: ['elem2', 'elem1'],
},
relation2: {
path: ['elem3', 'elem1'],
}
}
}
I am wondering if it possible to check at compile time if the path array contains values only within the domain of the keys of the elements key at root level.
I cannot understand if with the usage of keyof, generics, or some other Typescript features it is possible to define such relation.
EDIT: Thanks to Shahriar Shojib I got a first valid solution.
But I am wondering if it is possible to achieve this without employing a function, but simply specifying the type for the object.
Solution 1:[1]
I am sure there are better ways to achieve this, but this should work for your use case.
type ElemField = { name: string }
type Elem = Record<string, ElemField>
type Relation <T> = { path: T[] }
type MySchema<T extends Record<string, Elem>> = {
elem: T,
relations: Record<string, Relation<keyof T>>
}
function createSchema<T extends Record<string, Elem>>(schema:MySchema<T>) {
return schema;
}
createSchema({
elem: {
elem1: {
prop1: { name: 'string' },
},
elem2: {
prop2: { name: 'string' },
prop3: { name: 'string' },
},
elem3: {
prop4: { name: 'string' },
}
},
relations: {
relation1: {
path: ['elem2', 'elem1', 'elem5'], // error since it does not exist
},
relation2: {
path: ['elem3', 'elem1'],
}
}
})
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Shahriar Shojib |
