I'm trying to create examples of all the different ways to write functions and function type definitions in TypeScript.
One requirement is these examples must work with strict mode (noImplicitAny, etc) enabled.
If I'm missing anything, please add comments below with examples. I'll eventually put this into a blog post.
Keep in mind that there are TONS of combinations of different syntaxes. I only want to include those which are less obvious combinations or unique in some way.
// inferred return type
function sum(a: number, b: number) {
return a + b
}// defined return type
function sum(a: number, b: number): number {
return a + b
}const sum = function sum(a: number, b: number) {
return a + b
}const sum = function(a: number, b: number) {
return a + b
}const sum = (a: number, b: number) => {
return a + b
}const sum = (a: number, b: number) => a + bconst sum = (a: number, b: number): number => a + bconst sum = (a: number, b: number): number => a + bYou can also add a type annotation next to the variable, and then the function itself will assume those types:
const sum: (a: number, b: number) => number = (a, b) => a + bAnd you can extract that type:
type MathFn = (a: number, b: number) => number
const sum: MathFn = (a, b) => a + bOr you can use the object type syntax:
type MathFn = {
(a: number, b: number): number
}
const sum: MathFn = (a, b) => a + bWhich can be useful if you want to add a typed property to the function:
type MathFn = {
(a: number, b: number): number
operator: string
}
const sum: MathFn = (a, b) => a + b
sum.operator = '+'This can also be done with an interface:
interface MathFn {
(a: number, b: number): number
operator: string
}
const sum: MathFn = (a, b) => a + b
sum.operator = '+'And then there's declare function:
TODO (I'm not sure I understand this myself yet).
Given the interface:
interface Foo {
bar: string;
}You can write the following function to reasonably assert that x is a Foo:
function isFoo(x: any): boolean {
return typeof x.bar === string;
}By using the return signature here x is Foo rather than boolean, we can signal TypeScript to know our parameter's type:
function isFoo(x: any): x is Foo {
return typeof x.bar === string;
}
function baz(x: any) {
if (isFoo(x)) {
// inside this if, ts will give type-safety as it knows x is of Type Foo
console.log(x.bar);
}
}This can be especially helpful in 'splitting' a union type:
function baz(x: Foo | Buzz) {
if (isFoo(x)) {
// inside this if, ts will give type-safety as it knows x is of type Foo
console.log(x.bar);
return;
}
// TS now knows x must be of type Buzz here!
doSomethingYouCouldOnlyDoToABuzzObj(x);
}TODO
TODO
Object method:
const math = {
sum(a: number, b: number): number {
return a + b
},
}Property as function expression:
const math = {
sum: function sum(a: number, b: number): number {
return a + b
},
}Property as arrow function expression (whith implicit return):
const math = {
sum: (a: number, b: number): number => a + b,
}Unfortunately, to extract the type you can't type the function itself, you have to type the enclosing object:
type MathFn = (a: number, b: number) => number
const math: {sum: MathFn} = {
sum: (a, b) => a + b,
}Furthermore, if you want to add a property on it like above, then you have to extract the function definition as well:
type MathFn = {
(a: number, b: number): number
operator: string
}
const sum: MathFn = (a, b) => a + b
sum.operator = '+'
const math = {sum}You may have noticed that this example is identical to an example above with only the addition of the const math = {sum}. So yeah, there's no way to do all this inline with the object declaration.
TODO
TODO
TODO
TODO
TODO
TODO