microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.09k stars 12.37k forks source link

[Suggestion] a "const mode" where `as const` is by default for literals #51930

Open yw662 opened 1 year ago

yw662 commented 1 year ago

Suggestion

🔍 Search Terms

const by default, const mode, use const, as const

✅ Viability Checklist

My suggestion meets these guidelines:

⭐ Suggestion

An optional const mode, manually enabled by tsconfig or cli options or maybe a "use const" directive. In const mode, a selective subset of js literals (like all primitive literals, and usually arrays) are as const by default, eg.

'use const'
const bool = true // typeof bool is `true` instead of `boolean`
const foo = 'foo' // typeof foo is `foo` instead of `string`
const num = 0 // 0, instead of `number`
const tuple = [ 'foo', true ] // typeof tuple is readonly [ 'foo', true ]
const record = { 'foo': 'bar', 'bar': 0 } // typeof record is { 'foo': 'bar', 'bar': 0 }

or some alternative directives:

'use const string'
'use const primitive'
'use const Array'
'use const Object'

When the non-const type is wanted:

'use const'
let bool = true // suggested optionally: const mode can be disabled for `let`.
const arr: string[] = [ 'foo', 'bar' ] // manually declare the type

📃 Motivating Example

Literals, esp. primitive literals assigning to constant variables usually have a good chance to remain what they are during their whole lifetime. Applying as const by default can further improve type safety and convenience in projects where type safety is valued.

💻 Use Cases

Literally to type less as const.

xiBread commented 1 year ago

const strings, booleans, and numbers are already treated as literals.

Playgroud

yw662 commented 1 year ago

const strings, booleans, and numbers are already treated as literals.

Playgroud

That's super cool. Although what I really what is to apply as const by default to array literals and object literals.

Richiban commented 1 year ago

I would appreciate this as one of the strict mode options: when assigning to a const variable or a readonly member the compiler should infer that as const should be applied.

To be honest, I kinda wish there was a way that you could flip the mutability defaults across the whole language (perhaps introducing a mut keyword to opt in to mutability in given cases) but that's unlikely to happen. I'll settle for this!

xiBread commented 1 year ago

This seems similar to #42357

ezheidtmann commented 1 month ago

I want this too -- here's my real-life example

// this thing has a definite type
const value: "speed" | "direction" | "both";

// now I want to know which it is, but i've made a typo
if (["direction", "boooo"].includes(value)) { 
  // do the thing
}

TS will not help me here, unless I write (["direction", "boooo"] as const).includes(...). That's annoying, and everyone on the team has to remember to write "as const" forever more.

I'd rather turn on a "use const" mode per-file or across the whole project, and opt out of it with string[] type declarations when necesssary.

Thanks!