Skip to content

Add a flag which priorities unknown over any in any | unknownΒ #46347

Open

Description

@orta

Suggestion

πŸ” Search Terms

any vs unknown, any strict, unknown strict, unknown as any, any as unknown in strict

βœ… Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • 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, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

We have a lot of cases where we'd like to have folks opt-in to unknown instead of any in the eslib, DOM, DT and modules. We've discussed internally about the idea of a third primitive, but that's tricky because it requires finding a good word to describe that, would break .d.ts backwards compatibility and that's quite a fine-grained change.

I propose that we have a flag which lets unknown beat any in union narrowing, which we class as a part of the stricter than strict category.

Today all the way back to 3.6:

type A = any | unknown
//   ^? - type A = any

A future release

// @thisCompilerFlag: true

type A = any | unknown
//   ^? - type A = unknown

πŸ“ƒ Motivating Example

Anywhere where we use any but would prefer to offer a way to provide unknown instead, for example:

  • JSON.parse
  • The fetch / axios APIs
  • new Object / Object.create

πŸ’» Use Cases

Where the ecosystem breakage for moving from any are too big to warrant the move. I think switching out any | unknown is a pretty reasonable syntax which doesn't add a new concept to the language. It means anyone can adopt support without having to force updating TypeScript versions.

Activity

  1. orta commented on Oct 13, 2021

    @orta
    ContributorAuthor
  2. remcohaszing commented on Oct 15, 2021

    @remcohaszing

    I just though of an alternative solution which turns out to be really close to #45605

    Add a compiler option to forcefully turn any or unknown types which originate from a .d.ts file into either any or unknown when it reaches user code (.ts file). A user could still decide to use the any or unknown type in their own code. I think this also aligns, or could even supersede "useUnknownInCatchVariables".

    For example, given:

    a.d.ts:

    export declare const unknownA: unknown;
    export declare const anyA: any;

    b.ts:

    export declare const unknownB: unknown;
    export declare const anyB: any;

    This would be the behaviour:

    c.ts ({ "anyOrUnknownLibType": "as-is" } default)

    import { unknownA, anyA } from './a';
    import { unknownB, anyB } from './b';
    
    // $ExpectType unknown
    unknownA;
    
    // $ExpectType any
    anyA;
    
    // $ExpectType unknown
    unknownB;
    
    // $ExpectType any
    anyB;

    c.ts ({ "anyOrUnknownLibType": "any" })

    import { unknownA, anyA } from './a';
    import { unknownB, anyB } from './b';
    
    // $ExpectType any
    unknownA;
    
    // $ExpectType any
    anyA;
    
    // $ExpectType unknown
    unknownB;
    
    // $ExpectType any
    anyB;

    c.ts ({ "anyOrUnknownLibType": "unknown" })

    import { unknownA, anyA } from './a';
    import { unknownB, anyB } from './b';
    
    // $ExpectType unknown
    unknownA;
    
    // $ExpectType unknown
    anyA;
    
    // $ExpectType unknown
    unknownB;
    
    // $ExpectType any
    anyB;

    I think the benefit of this is that:

    • Library types don’t need to be adjusted
    • The user is in control
  3. ITenthusiasm commented on Oct 15, 2021

    @ITenthusiasm

    If possible, I think remcohaszing's #46347 (comment) may actually work out more cleanly.

    The ability to simultaneously lighten the burden on authors and place control in the user's hands is pretty game changing. It would hopefully help reduce confusion too. (I feel like any | unknown could be confusing for some... and it would require some updates to the docs.)

  4. 43081j commented on Feb 21, 2023

    @43081j

    can we possibly have a strict compiler flag which just introduces an extra built in library file? one which overrides the usual one, by setting various types to unknown

    e.g. have it override JSON.parse to return unknown

    we could then just maintain that alongside the standard lib files?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions