0

My question is pretty simple here, I would like to understand the the relationship between casting a literal with as const and the infer of a generics.

Here a sample repro:

declare global {
    interface String {
        // @ts-expect-error Simulate skipLibCheck
        toUpperCase<T>(this: T): Uppercase<T>;
    }
}
export {};

const strA = "mylowercasedstring"; // typed as "mylowercasedstring" (literal)
const strB = "mylowercasedstring" as const; // also typed as "mylowercasedstring" (literal)
const resultA = strA.toUpperCase(); // typed as string
const resultB = strB.toUpperCase(); // typed as "MYLOWERCASEDSTRING" (literal)
// why?

Why resultA is not properly infered like resultB?

lsagetlethias
  • 328
  • 2
  • 14
  • 1
    Does this answer your question? [What does the "as const" mean in TypeScript and what is its use case?](https://stackoverflow.com/questions/66993264/what-does-the-as-const-mean-in-typescript-and-what-is-its-use-case) – ldruskis Feb 23 '22 at 10:09
  • Thanks for the suggestion ! But no because I already know the assertion / readonly part of a `as const` cast. My question is more about how it's linked with infering into the compiler. – lsagetlethias Feb 23 '22 at 10:21
  • 1
    I don't have the answer but try `const toUpper = (x: T) => x.toUpperCase()` on `strA`... It's kind of funny. I was first assuming that, because you call a method on a string, JS is boxing it in a String object before running the function which widens the type to `string`, as if you were calling `String` on it, and TS would somehow treat `as const` differently but it's not what is happening, and calling `String` on `strB` confirms that – geoffrey Feb 24 '22 at 20:18
  • Hello! Thank you for the answer! Yeah, I could do that, I could also remove the `skipLibCheck` and type `toUpperCase` like you did `toUpperCase(...)` ; But I don't try to find a way make it work, as I already know that ; I try to understand why it **doesn't** work :p – lsagetlethias Feb 25 '22 at 16:49

0 Answers0