Reputation: 4365
I've built this snippet to demonstrate my question:
const typeEnum = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5
};
const isCD = (...types: any[]) => {
return types.some(t => {
return t == typeEnum.c || t == typeEnum.d;
});
};
console.log(
isCD(
typeEnum.a,
typeEnum.b,
typeEnum.d,
6
)
);
So what I want is to replace any[]
to the correct type, but I don't know how to set that the acceptable values are the ones from typeEnum
keys, so no one would pass 6
as argument because it is not an acceptable argument.
Thanks in advance.
My final working snippet ended this way:
const typeEnum = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5
} as const;
type typeEnumValues = typeof typeEnum [keyof typeof typeEnum];
const isCD = (...types: typeEnumValues[]) => {
return types.some(t => {
return t == typeEnum.c || t == typeEnum.d;
});
};
console.log(
isCD(
typeEnum.a,
typeEnum.b,
typeEnum.d,
6
)
);
Upvotes: 2
Views: 108
Reputation: 327744
For TS3.4+ you can use a const
assertion to tell the compiler the type of typeEnum
should be inferred to be as narrow as possible... a property value of 3
will be inferred as the numeric literal 3
and not as number
:
const typeEnum = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5
} as const;
// inferred as type { readonly a: 1; readonly b: 2; readonly c: 3;
// readonly d: 4; readonly e: 5; }
If you haven't updated to TS3.4 yet you can get similar behavior with a helper function:
const litNumVals =
<N extends number, T extends { [k: string]: N }>(t: T) => t;
const typeEnum = litNumVals({
a: 1,
b: 2,
c: 3,
d: 4,
e: 5
});
// inferred as type { a: 1; b: 2; c: 3; d: 4; e: 5; }
From that value, you can use type functions to constrain isCD
parameters:
type ValueOf<T> = T[keyof T]
type TypeEnumValues = ValueOf<typeof typeEnum>;
// 1 | 2 | 3 | 4 | 5
const isCD = (...types: Array<TypeEnumValues>) => {
return types.some(t => {
return t == typeEnum.c || t == typeEnum.d;
});
};
console.log(
isCD(
typeEnum.a, // okay
typeEnum.b, // okay
typeEnum.d, // okay
6 // error
)
);
Okay, hope that helps. Good luck!
Upvotes: 1
Reputation: 3594
You can't define a type
from a const
, but you can define the const
's type.
Is this solution OK for your use case?
type AcceptedValue = 1 | 2 | 3 | 4 | 5;
const typeEnum : {[key: string]: AcceptedValue} = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5
};
Upvotes: 1