TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

Generic types extending Record<Uppercase<string>, ...> ignore the Uppercase utility

Open sadkebab opened this issue 4 months ago • 1 comments

🔎 Search Terms

Record<Uppercase Uppercase

🕗 Version & Regression Information

I tested the following snippet on the playground with all versions starting from 4.9.5 and the behaviour was the same. For all the previous versions down to 4.1 (when Uppercase was introduced) the behaviour was different but the errors seem unrelated.

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.6.3#code/C4TwDgpgBAqmkCcDGBDAzhAShJB7BAJlALxTZ6EA8ciqGlawCAlgHYDmAfADRQCurANatcAd1acA3AChpAMwFJgzXKyhzcuSgBUoEAB7AIrAmljwIydFhz4CnABQAjFAgBcUbQEooAb2lQUAgQwHwIai4IMgC+sgD0cVDAABbMZmjJuHwANkQpCGJQKGqWBQjSeKyMUBlZuQBiKMzZJOqaDv6BGrgeAESRvdzS0V4yspXVck3ZaADqzCkAyijKaHLMEGak3R0BbT1Q-a6DwzUraeub5rTW5Haj46rVC7P4glv7u4H1API-fQMhiMxhNgFAXm85gtkstVpc0NpNK0dp0oL9-odAac0Oc1hszDRLHQbBQCA9pAkoKJkitwXIqdACKoAORgvgYcFgthFKDsYyWZhIdSKZSqAD88hFKjUoEgBHq7UiHkJVgwd0IPlRwVC4SgkRi8USKWgsugokhFSeXOAjWaH1N8vaqO6AOOQNGQA

💻 Code

type UppercaseRecord = Record<Uppercase<string>, unknown>;

function foo<T extends UppercaseRecord>(bar: T) {
  return bar;
}

// this should throw an error
const shouldFail = foo({
  foo: "bar",
});

const failsWithSatisfies = foo({
  foo: "bar",
} satisfies UppercaseRecord);

const itWorks = foo({
  FOO: "bar",
});

const itWorksWithSatisfiesToo = foo({
  FOO: "bar",
} satisfies UppercaseRecord);

// what if we don't use it in a generic function?
function typedFoo(bar: UppercaseRecord) {
  return bar;
}

const itFails = typedFoo({
  foo: "bar",
});

🙁 Actual behavior

Passing a record with lowercase properties on foo does not throw an error.

🙂 Expected behavior

Passing a record with lowercase properties on foo should throw an error.

Additional information about the issue

Generic types extending Uppercase<...> seem to work properly.

function foo<T extends Uppercase<string>>(bar: T) {
  return bar;
}

foo("FOO");

// this throws an error
foo("foo");

sadkebab avatar Oct 20 '24 12:10 sadkebab