-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Issues with parameterizing over a union type #13073
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
if your function expects a value that is either if your result depends on which value you pass, e.g. The evaluation of the constraint for generic indexed access type is delayed until instantiation time. doing it earlier will allow you to access the For instance: type KeyTypes = "a" | "b"
let MyThingy: {
a: string;
b: number;
};
function genericGet<S extends KeyTypes>(key: S) {
return MyThingy[key];
}
var g = genericGet("b"); // number
function concreateGet(key: KeyTypes) {
return MyThingy[key];
}
var c = concreateGet("b"); // string | number |
I see what you're saying about the constraints being delayed until instantiation. But isn't it possible to determine that Unfortunately, I really do need the generic type. This is a minimum reproducible example of a much larger project. |
if you can use it as an array then the result will be the union type as well. do not think |
This might be more representative of what he's asking: interface Foo{
prop1: string;
prop2: number;
}
type PropertyEditCount = {
[key in keyof Foo]: number
}
const propEditCount: PropertyEditCount = {
prop1: 0,
prop2: 0
}
const foo:Foo = {
prop1: 'bar',
prop2: 42
}
class FooPropertyEditor<T extends keyof Foo>{
setVaue(key: T, value: Foo[T]): void{
foo[key] = value;
propEditCount[key] = propEditCount[key]+1;//Operator + cannot be applied to types PropertyEditCount[T] and '1'
}
} Why can't |
for |
I don't think that's the crux of it. The fundamental question is why the parameterized is not being fully resolved at compile time. Take a slightly different example without +: interface Foo{
prop1: string;
prop2: number;
}
type DateEditedCount = {
[key in keyof Foo]: Date[]
}
const propEditCount: DateEditedCount= {
prop1: [],
prop2: []
}
const foo:Foo = {
prop1: 'bar',
prop2: 42
}
class FooPropertyEditor<T extends keyof Foo>{
setVaue(key: T, value: Foo[T]): void{
foo[key] = value;
propEditCount[key] = propEditCount[key].push(new Date()); //ERROR Property 'push' does not exist on type 'DateEditedCount[T]'
}
} |
In that last example we know that |
this is a special case, where the type of |
It is not uncommon to define a type that maps all keys of another type to a common type. I don't know anything about the compiler implementation or complexities involved, but would it be worth supporting this case such that if the union of all the possible |
the issue is not the mapped type. it is the index access with a generic type, i.e. you could define |
Ok.. I think I have a better understanding of the issue now.. Thanks for your help. |
Returning to the original question, I do think we could do better. interface Item {
a: string;
b: string;
}
function f1(x: Item[keyof Item]) {
x.length; // Ok
}
function f2<T extends Item>(x: T[keyof Item]) {
x.length; // Ok
}
function f3<K extends keyof Item>(x: Item[K]) {
x.length; // Error
}
function f4<T extends Item, K extends keyof Item>(x: T[K]) {
x.length; // Error
} In the two error cases above we know from the constraint that |
Whoa, awesome! Thanks! |
Why does this code work:
And this code fail?
Unless I've misunderstood
S extends KeyTypes
, all I've done is constrainedkey
to be "a" or "b" with my type parameter.The text was updated successfully, but these errors were encountered: