Skip to content

Instantly share code, notes, and snippets.

@hatemhosny
Last active February 11, 2021 20:50
Show Gist options
  • Save hatemhosny/4bed283ef9757a6a541aee685c710dc7 to your computer and use it in GitHub Desktop.
Save hatemhosny/4bed283ef9757a6a541aee685c710dc7 to your computer and use it in GitHub Desktop.
Compiled Code
// TypeScript's inference can get you very far, but there
// are lots of extra ways to provide a richer way to document
// the shape of your functions.
// A good first place is to look at optional params, which
// is a way of letting others know you can skip params.
let i = 0;
const incrementIndex = (value?: number) => {
i += value === undefined ? 1 : value;
};
// This function can be called like:
incrementIndex();
incrementIndex(0);
incrementIndex(3);
// You can type parameters as functions, which provides
// type inference when you write the functions.
const callbackWithIndex = (callback: (i: number) => void) => {
callback(i);
};
// Embedding function interfaces can get a bit hard to read
// with all the arrows. Using a type alias will let you name
// the function param.
type NumberCallback = (i: number) => void;
const callbackWithIndex2 = (callback: NumberCallback) => {
callback(i);
};
// These can be called like:
callbackWithIndex(index => {
console.log(index);
});
// By hovering on index above, you can see how TypeScript
// has inferred the index to be a number correctly.
// TypeScript inference can work when passing a function
// as an instance reference too. To show this, we'll use
// a function which changed a number into string:
const numberToString = (n: number) => {
return n.toString();
};
// This can be used in a function like map on an array
// to convert all numbers into a string, if you hover
// on stringedNumbers below you can see the expected types.
const stringedNumbers = [1, 4, 6, 10].map(i => numberToString(i));
// We can use shorthand to have the function passed directly
// and get the same results with more focused code:
const stringedNumbersTerse = [1, 4, 6, 10].map(numberToString);
// You may have functions which could accept a lot of types
// but you are only interested in a few properties. This is
// a useful case for indexed signatures in types. The
// following type declares that this function is OK to use
// any object so long as it includes the property name:
interface AnyObjectButMustHaveName {
name: string;
[key: string]: any;
}
const printFormattedName = (input: AnyObjectButMustHaveName) => {};
printFormattedName({ name: "joey" });
printFormattedName({ name: "joey", age: 23 });
// If you'd like to learn more about index-signatures
// we recommend:
//
// https://www.typescriptlang.org/docs/handbook/interfaces.html#excess-property-checks
// https://basarat.gitbooks.io/typescript/docs/types/index-signatures.html
// You can also allow this kind of behavior everywhere
// via the tsconfig flag suppressExcessPropertyErrors -
// however, you can't know if others using your API have
// this set to off.
// Functions in JavaScript can accept different sets of params.
// There are two common patterns for describing these: union
// types for parameters/return, and function overloads.
// Using union types in your parameters makes sense if there
// are only one or two changes and documentation does not need
// to change between functions.
const boolOrNumberFunction = (input: boolean | number) => {};
boolOrNumberFunction(true);
boolOrNumberFunction(23);
// Function overloads on the other hand offer a much richer
// syntax for the parameters and return types.
interface BoolOrNumberOrStringFunction {
/** Takes a bool, returns a bool */
(input: boolean): boolean;
/** Takes a number, returns a number */
(input: number): number;
/** Takes a string, returns a bool */
(input: string): boolean;
}
// If this is your first time seeing declare, it allows you
// to tell TypeScript something exists even if it doesn't
// exist in the runtime in this file. Useful for mapping
// code with side-effects but extremely useful for demos
// where making the implementation would be a lot of code.
declare const boolOrNumberOrStringFunction: BoolOrNumberOrStringFunction;
const boolValue = boolOrNumberOrStringFunction(true);
const numberValue = boolOrNumberOrStringFunction(12);
const boolValue2 = boolOrNumberOrStringFunction("string");
// If you hover over the above values and functions you
// can see the right documentation and return values.
// Using function overloads can get you very far, however
// there's another tool for dealing with different types of
// inputs and return values and that is generics.
// These provide a way for you to have types as placeholder
// variables in type definitions.
// example:generic-functions
// example:function-chaining
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment