Reputation: 245
I'm trying to make a framework with typescript.
and I need a compile time data check.
type TypeInfo = 'string' | 'number' | 'boolean';
type GetType<T extends TypeInfo> = T extends 'string'
? string
: T extends 'number'
? number
: T extends 'boolean'
? boolean
: never;
interface StateInfo {
// TypeInfo
type: TypeInfo;
default: GetType<this['type']>;
}
// OK
const test1: StateInfo = {
type: 'number',
default: 1,
};
// Bad ('default' property is not number or 'type' property is not 'string')
const test2: StateInfo = {
type: 'number',
default: 'test',
};
But, the typescript compile the code without any errors.
How can I declare type of 'default'
property correctly?
Upvotes: 1
Views: 1729
Reputation: 33111
@Shivam Singla 's answer is perfectly valid and I believe should be accepted. Please treat my answer as add-on )
If you want to infer smth, the best way, I believe, to use function with generics:
type TypeInfo = 'string' | 'number' | 'boolean';
type GetType<T extends TypeInfo> = T extends 'string'
? string
: T extends 'number'
? number
: T extends 'boolean'
? boolean
: never;
interface StateInfo {
// TypeInfo
type: TypeInfo;
default: GetType<this['type']>;
}
const test = <T extends TypeInfo>(arg: T, prop: GetType<T>): StateInfo => {
// this return valu is just a mock, you should provide here your valid code
return null as any
}
const result = test('string','str') // ok
const result2 = test('number',1) // ok
const result3 = test('boolean', true) // ok
const result4 = test('boolean', 1) // expected error
const result5 = test('string', false) // expected error
Now, your StateInfo
is doing what you want.
Upvotes: 2
Reputation: 2201
GetType<this['type']>
is evaluated during declaration of StateInfo
. What I mean is that, the type of default
will be string | number | boolean
and will not be affected by the value of property type
while creating objects.
type StateInfoString = {
type: 'string'
default: string
}
type StateInfoNumber = {
type: 'number'
default: number
}
type StateInfoBoolean = {
type: 'boolean'
default: boolean
}
type StateInfo = StateInfoString | StateInfoNumber | StateInfoBoolean
// OK
const test1: StateInfo = {
type: 'number',
default: 1,
};
// error
const test2: StateInfo = {
type: 'number',
default: 'test',
};
Upvotes: 4