Search code examples
arraystypescripttype-inference

Understanding TypeScript Type System: Issue with Generated Arrays and Const Assertions


I believe I'm facing a fundamental understanding issue with TypeScript, as evidenced by the behavior in the following code snippet. I'm trying to understand why a generated array isn't working and if there's a way to resolve this.

typescript

const mySlugs = ['post1', 'post2'] as const // working
const mySlugs = (allPosts.map(post => post._raw.sourceFileName)) as const  // not working
export type SlugType = (typeof mySlugs)[number]

The first line (const mySlugs = ['post1', 'post2'] as const;) works as expected, but the second line (const mySlugs = (allPosts.map(post => post._raw.sourceFileName)) as const;) doesn't (A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.ts(1355)).

Is there something I'm misunderstanding about TypeScript's type system or const assertions? Any insights or suggestions would be greatly appreciated!


Solution

  • The as const assertion can only be used on simple literals, not expressions in general. From the documentation for the release where it was added:

    Caveats

    One thing to note is that const assertions can only be applied immediately on simple literal expressions.

    That's what the error message says as well:

    A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals. (1355)

    If you want to make your generated array read-only, you can use the ReadOnlyArray utility type:

    const mySlugs = allPosts.map(post => post._raw.sourceFileName) as ReadonlyArray<string>;
    

    But that only does one of the three things as const would do on a literal, so the result will be an array of string, not a tuple containing string literal types.