Skip to content

const number and strings make automatic literals #31211

@TheDSCPL

Description

@TheDSCPL

Search Terms

const string typescript literals

Suggestion

I was defining constants to be used as Redux action types and was surprised to see that constant strings had type string!
My suggestion is that variables declared with the const keyword should have the most specific type possible, which is, in the case of strings and numbers, literals.

Please, either make constant strings and numbers be literals by default or provide a keyword or operator which can be used to force the string or number to have the literal type

Use Cases

const helloWorldActionType =  '@@reducerName/helloWorld';
const goodbyeWorldActionType =  '@@reducerName/goobyeWorld';
interface IAction<T extends string,P> {
    type: T;
    payload: P;
}
function helloWorld(name: string): IAction<typeof helloWorldActionType, string> {
    return {
        type: helloWorldActionType,
        payload:  `Hello world! I'm ${name}.`
    }
}
function goobyeWorld(name: string): IAction<typeof goodbyeWorldActionType, number> {
    return {
        type: goodbyeWorldActionType,
        payload: name.length
    }
}
type Actions = ReturnType<typeof helloWorld | typeof goobyeWorld>;
const reducer: Reducer<ThisReducersStateType,Actions> = (state, action) => {
    switch(action.type) {
        case helloWorldActionType:
            // this case doesn't make 'action' be considered as of type 'IAction<typeof helloWorldActionType, string>' because 'helloWorldActionType' is of type 'string'
            const str: string = action.payload; // "action.payload" is still "string | number", which creates an error...
    // ...
}

This can be fixed with

const helloWorldActionType =  '@@reducerName/helloWorld' as '@@reducerName/helloWorld';

but it makes no sense... helloWorldActionType should be of type '@@reducerName/helloWorld' instead of string without the cast because it's a constant and can never change to another string other than that one.

This is annoying because I really don't want to have to type the string twice (not DRY), once in the value and again in the cast, every time I create a constant string.

Examples

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code (every code which declares a constant string or number can't change the value later on so there is no problem in TypeScript now considering such variables as literals)
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions