Skip to content

Instantly share code, notes, and snippets.

@nilshartmann
Created November 22, 2022 12:26
Show Gist options
  • Save nilshartmann/53f74fa10dbb6a4145601f57988b7933 to your computer and use it in GitHub Desktop.
Save nilshartmann/53f74fa10dbb6a4145601f57988b7933 to your computer and use it in GitHub Desktop.
export default undefined;
type Container<T> = {
consume: (arg: T) => void;
};
// string ist super-type von "hello" 😳
// Entspricht in C# sowas hier:
// public class Event { } // => string
// public class MouseEvent : Event { } // => "hello"
type StringType = string;
type HelloType = "hello";
let superType: StringType = "irgendwas";
let subType: HelloType = "hello";
// Dem allgemeinen Typen kann in eine spezialisierung zu weisen!
// alles was auf subType definiert ist, muss ja auch in supertype vorhanden sein
superType = subType; // ok
// dem SPEZIALISIERTEN Typen kann ich aber nicht den allgemeinen zuweisen
// (das ist wie in OO-Sprachen), denn im SPEZIALISIERTEN erwarte ich ja
// eigene bzw. mehr/andere Eigenschaften, die im ALLGEMEINEN (super) Type möglicherweise
// nicht vorhanden sind
subType = superType; // error
let containerWithString: Container<StringType> = {
// string
consume: arg => {}
};
containerWithString.consume("OK"); // OK => beliebiger string
containerWithString.consume("hello"); // OK => spezialisierter string
let containerWithHello: Container<HelloType> = {
// "hello"
consume: arg => {}
};
containerWithHello.consume("OK"); // FEHLER => beliebiger string
containerWithHello.consume("hello"); // OK => spezialisierter string
// Hier kann ich den SPEZIALISIERTEN Typen ('hello') NICHT
// an den ALLGEMEINEN Typen ("") zuweisen.
// Wenn das FUNKTIONIEREN WÜRDE, könnten wir plötzlich containerWitHello
// mit jedem beliebigen String aufrufen
containerWithString = containerWithHello; // error
containerWithString.consume("xxx"); // wenn Zeile davor gehen würde => 💥
// Dem spezialisierten Typ wird der ALLGEMEINE Typ zugewiesen
// DAS wiederrum geht hier, denn wir können nun containerWitHello
// nur mit "hello" aufrufen, und damit kommen beide Typen klar
containerWithHello = containerWithString; // ok
containerWithHello.consume("hello");
containerWithHello.consume("..."); // FEHLER
// Functions are contravariant in their parameter types,
// so unions of functions correspond to intersections
// of function parameters, and vice versa.
type Callback<T> = (value: T) => void;
type StringCallback = Callback<string>;
const stringCallbackFn: StringCallback = value => {};
stringCallbackFn("something");
stringCallbackFn("");
type HelloCallback = Callback<"hello">;
const helloCallbackFn: HelloCallback = value => {};
helloCallbackFn("something"); // nope
helloCallbackFn("hello"); // of course
type X = string & "";
const x: X = ""; // OK
const xx: X = "falsch"; // nö...
function runCallback(callback: StringCallback | HelloCallback) {
// Ich muss ALLE eigenschaften von Callback beim Aufrufen
// berücksichtigen!
callback("hello"); // SUB type !!!
callback("nope"); // SUPER TYPE!
}
type NumberCallback = Callback<number>;
const numberCallbackFn: NumberCallback = value => {};
numberCallbackFn("something"); // nope
numberCallbackFn(123); // of course
function runCallbackWithNumberAndString(callback: StringCallback | NumberCallback) {
// Ich muss ALLE eigenschaften von Callback beim Aufrufen
// berücksichtigen!
// => Das ist hier unmöglich
callback(1); // Schade...
callback("nope"); // Auch schade
}
function doSomething(x: string | number) {
// GEHT BEIDES... hier UNION TYPE!
x = 3;
x = "hallo";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment