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
A mapped generic type does not work as intended in a generic function #51290
Comments
Specifically the issue here is key remapping involving generics. Template literal types don't seem to be part of the cause: type MyPrefixedType<P extends string> = {
[K in "xxx" as P]: string
}
function createPrefixedType<P extends string>(prefix: P): MyPrefixedType<P> {
type Z = MyPrefixedType<P>;
// type Z = {};
return {}; // No error!
}
const x = createPrefixedType("XYZ");
console.log(x.XYZ.toUpperCase()); // typed as string! That's obviously a silly thing to do with key remapping, but it illustrates the same issue, I think. |
This was fixed by #51050. The fix will be in the upcoming 4.9 release. |
@ahejlsberg Thanks! The object in the function has the correct type, however, the assignment still creates an error. type MyPrefixedTypeKeys =
'foo' |
'bar';
type MyPrefixedType<P extends string> = {
[K in MyPrefixedTypeKeys as `${P}${K}`]: string
}
// Ok
type test = MyPrefixedType<'pre_'>; // { pre_foo: string, pre_bar: string }
let o: test = { pre_bar: '', pre_foo: '' };
o[`pre_bar`] = '';
function createPrefixedType<P extends string>(prefix: P): MyPrefixedType<P> {
let o: MyPrefixedType<P> = { // Ok
[`${prefix}foo`]: '',
[`${prefix}bar`]: '',
} as MyPrefixedType<P>;
type x = MyPrefixedType<P>; // The type is correct now
// but the error still is there
o[`${prefix}bar`] = ''; // Type 'string' is not assignable to type 'MyPrefixedType<P>[`${P}bar`]'.(2322)
return o;
} |
Ah, there are actually a couple of issues in play here. The first, illustrated by @jcalz's example, is that we would eagerly resolve The second issue is the error on the assignment o[`${prefix}bar`] = ''; The type checker is rather conservative when analyzing assignments to types of the form type MyPrefixedTypeKeys =
'foo' |
'bar';
type MyPrefixedType<P extends string> = {
[K in `${P}${MyPrefixedTypeKeys}`]: string
}
function createPrefixedType<P extends string>(prefix: P): MyPrefixedType<P> {
let o: MyPrefixedType<P> = {
[`${prefix}foo`]: '',
[`${prefix}bar`]: '',
} as MyPrefixedType<P>;
o[`${prefix}bar`] = ''; // Ok
return o;
} |
@ahejlsberg Sorry for the late reply. I have found a workaround to express it in a Record type * (since in my particular case, all values in the type where strings) which worked in the older version and I somehow forgot about this thread. It's definitely good to know that it's possible though. Thank you, sir! type MyPrefixedType<Prefix extends string> = Record<`${Prefix}_${MyPrefixedTypeKeys}`, string> |
Bug Report
π Search Terms
mapped types generic
π Version & Regression Information
Not a regression.
This is the behavior in every version I tried, and I reviewed the FAQ.
β― Playground Link
Playground link with relevant code
π» Code
π Actual behavior
The mapped type becomes
{ }
in the generic.π Expected behavior
The type mapped type should work inside the generic.
Workarounds
In this particular case, it's possible to use
Record
as a workaround.The text was updated successfully, but these errors were encountered: