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.

Support some non-structural (nominal) type matching

See original GitHub issue

Issue Description

Proposal: support non-structural typing (e.g. new user-defined base-types, or some form of basic nominal typing). This allows programmer to have more refined types supporting frequently used idioms such as:

  1. Indexes that come from different tables. Because all indexes are strings (or numbers), it’s easy to use the an index variable (intended for one table) with another index variable intended for a different table. Because indexes are the same type, no error is given. If we have abstract index classes this would be fixed.

  2. Certain classes of functions (e.g. callbacks) can be important to be distinguished even though they have the same type. e.g. “() => void” often captures a side-effect producing function. Sometimes you want to control which ones are put into an event handler. Currently there’s no way to type-check them.

  3. Consider having 2 different interfaces that have different optional parameters but the same required one. In typescript you will not get a compiler error when you provide one but need the other. Sometimes this is ok, but very often this is very not ok and you would love to have a compiler error rather than be confused at run-time.

Proposal (with all type-Error-lines removed!):

// Define FooTable and FooIndex
nominal FooIndex = string;  // Proposed new kind of nominal declaration.
interface FooTable {
  [i: FooIndex]: { foo: number };
}
let s1: FooIndex;
let t1: FooTable;

// Define BarTable and BarIndex
nominal BarIndex = string; // Proposed new kind of nominal declaration.
interface BarTable {
  [i: BarIndex]: { bar: string };
}
let s2: BarIndex;
let t2: BarTable;

// For assignment from base-types and basic structures: no type-overloading is needed.
s1 = 'foo1';
t1 = {};
t1[s1] = { foo: 1 };

s2 = 'bar1';
t2 = { 'bar1': { bar: 'barbar' }};

console.log(s2 = s1); // Proposed to be type error.
console.log(s2 == s1); // Proposed to be type error.
console.log(s2 === s1); // Proposed to be type error.

t1[s2].foo = 100; // Gives a runtime error. Proposed to be type error.
t1[s1].foo = 100;

function BadFooTest(t: FooTable) {
  if (s2 in t) {  // Proposed to be type error.
    console.log('cool');
    console.log(t[s2].foo); // Proposed to be type error.
  }
}

function GoodBarTest(t: BarTable) {
  if (s2 in t) {
    console.log('cool');
    console.log(t[s2].bar);
  }
}

BadFooTest(t1); // Gives runtime error;
BadFooTest(t2); // No runtime error, Proposed to be type error.
GoodBarTest(t1); // Gives runtime error; Proposed to be type error.
GoodBarTest(t2);

Issue Analytics

  • State:open
  • Created 8 years ago
  • Reactions:885
  • Comments:422 (65 by maintainers)

github_iconTop GitHub Comments

102reactions
RyanCavanaughcommented, Sep 15, 2017

Collecting use cases from this thread

  • Functions with special behavior (e.g. functions with / without side effects)
  • Types with identical fields but different semantics (e.g. Customer vs Client but both are People, our own brands on various Node kinds)
  • Poor man’s units-of-measure
  • Identifying “kinds” of primitive data (normalized paths, URL-encoded strings, etc)
    • IDs - CustomerID and OrderID are both number but should never interchange
    • Keys (e.g. strings that are only valid for indexing into a certain sort of object)
    • Pointers (e.g. keys for an object map)
  • Unscrewing empty types (opaque handles)
56reactions
samwgoldmancommented, Jul 23, 2014

Regarding a name, what about “nominal” types? Seems pretty common in literature.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Support some non-structural (nominal) type matching #202
Proposal: support non-structural typing (e.g. new user-defined base-types, or some form of basic nominal typing). This allows programmer to ...
Read more >
Nominal types in TypeScript | Dimitrios Lytras
Improving our type-safety with fine-grained types. ... Opaque Types · [GitHub] Support some non-structural (nominal) type matching #202 ...
Read more >
Documentation - Type Compatibility - TypeScript
Structural typing is a way of relating types based solely on their members. This is in contrast with nominal typing. Consider the following...
Read more >
Opaque Types | beraliv
Structural type system, workaround in TypeScript, unique symbol and ... issue: Support some non-structural (nominal) type matching #202.
Read more >
Mark Dalgleish auf Twitter: „@naman34 Since TypeScript v3.9 ...
You can use it to ensure that your type checking is working correctly and that invalid ... Support some non-structural (nominal) type matching...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

Atomic type discrimination (nominal atomic types) in TypeScript - Stack Overflow
Read More >

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