question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[DRAFT/RFC] `Uncertain` type

See original GitHub issue

Suggestion

🔍 Search Terms

uncertain typecheck runtime

✅ 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

Add uncertain type to notify there is a chance the input won’t be exactly the type as you wish.

📃 Motivating Example

Here’s an example:

// in ts code, this is normal and well
export function foobar(x: number) {
    return x % 2 ? "foo" : "bar"
}

// in js code, however
foobar("2")
// but the error message does not help

Here’s how you could solve it:

// in ts code, this is normal and well, Uncertain accepts any type except unknown, undefined and null
export function foobar(x: Uncertain<number>) {
    if (!Number.isInteger(x)) {
        throw "x is not a number"
    } else { // x must be a number (and an integer)
        return x % 2 ? "foo" : "bar"
    }
}

// in js code, now we will get a better error message
foobar("2")

However, if you have multiple other checks, they might fail as well. Thus, even after strong runtime assertion, we still consider the uncertain variable to still be uncertain:

// in ts code, this is normal and well
export function foobar(x: Uncertain<number>) {
    if (!Number.isInteger(x)) {
        throw "x is not a number"
    }
    // Error: x is uncertain
    return x % 2 ? "foo" : "bar"
}

// in js code, now we will get a better error message
foobar("2")

For this situation, you use ! postfix operator to assert certainty:

// in ts code, this is normal and well
export function foobar(x: Uncertain<number>) {
    if (!Number.isInteger(x)) {
        throw "x is not a number"
    }
    
     // force x to be one of the type in Uncertain<number> which is number
    return x! % 2 ? "foo" : "bar"
}

// in js code, now we will get a better error message
foobar("2")

💻 Use Cases

It’s very simple: sometime you aren’t so sure whether your input really is the right type in runtime, especially for JS to TS interop. Sometimes due to lack of information you might have entered a string equivalent of the number while TS “expects” number. This would of course fail, but the error message could be cryptic, and also we should be able to take care of this bad expected type situation by hand preemptively.

Prior Art

fabiandev/ts-runtime

janjakubnanista/ts-type-checked

#1573

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:2
  • Comments:11 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
forabi-cosunocommented, Jul 12, 2022

Maybe a better alternative is to allow a function to define whether it could throw, and if so, what type of errors:

function validate(): number, throws RangeError {
  if (Number.isInteger(x)) {
    return x;
  }
  throw new RangeError() // Works
  // throw new TypeError() // Does not work. TypeError is not assignable to RangeError
}
1reaction
Josh-Cenacommented, Jul 7, 2022

Could it be a declaration emit feature? For example, all Uncertain<T> gets re-written to T in the emitted declaration, but during compilation, it’s treated as unknown.

Read more comments on GitHub >

github_iconTop Results From Across the Web

BIG-IP DNS support for DNS Resource Record type 65 (SVCB ...
DNS Type 65 is a draft RFC for HTTPS binding. At this time, this record type is not currently supported on certain features...
Read more >
ENUM Enhancement per Kaplan Draft RFC [Cisco Unified ...
The ENUM enhancement per Kaplan draft RFC provides source-based routing, that is, SIP-to-SIP calls can be routed based on the source SIP ...
Read more >
TLS Encrypted Client Hello draft-ietf-tls-esni-15
TLS Encrypted Client Hello draft-ietf-tls-esni-15 ; Consensus boilerplate, Unknown ; Telechat date, (None) ; Responsible AD, (None) ; Send notices ...
Read more >
Profiles and Parameters — Traffic Control 7.1.0 documentation
A Profile that can be used with either an Edge-tier or Mid-tier cache server (but not both, in general). This is the only...
Read more >
Function types and impl trait
Draft RFC : Named function types ... f(None); // call with `Option<_>`, unknown value type f(Some(22_i32)); // call again with `Option<i32>` }.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found