Skip to content

Latest commit

 

History

History
110 lines (97 loc) · 3.23 KB

20211127163402-typescript.org

File metadata and controls

110 lines (97 loc) · 3.23 KB

typescript

Generics

type numArray = Array<number>
type arr = Array<string>

const last = <T>(arr: T[]): T => {
   return arr[arr.length - 1];
}

const l = last([1,2,3])
const l2 = last(["a","b","c"])
const l3 = last<string>(["a","b","c"])
const makeArr = <X, Y>(x: X, y: Y): [X, Y] => {
    return [x, y];
}

const v = makeArr(5,6)
const v2 = makeArr("a","b")
const v3 = makeArr<string | null, number>("a",5)

makeArr: 2 generics, return, explicitly overwrite type inference, default value:

const makeArr = <X, Y=number>(x: X, y: Y): [X, Y] => [x, y]
const v3 = makeArr<string | null>("a",5)

To constrain what the user can actually pass to the generic:

const makeFullName = <T extends {firstName: string; lastName: string}>(obj: T) => {
    return {
        ...obj,
        fullName: obj.firstName + '' + obj.lastName
    }
}

const v4 = makeFullName({ firstName: "bob", lastName: "junior", age: 15 })
// const v5 = makeFullName({ another: "bob", lastName: "junior", age: 15 })

To use generic with interface:

interface Tab {
    id: string
    position: number
    data: any
}

We don’t really know what this data could be, maybe some tab we want to have one value and another tab we want different values so this is another one where we could either put the word any or maybe we want to take a generic. So if we want to take a generic we can do like this

interface Tab<T> {
    id: string
    position: number
    data: T
}

type NumberTab = Tab<number>
type StringTab = Tab<string>

From line 62: this is equivalent to

type NumberTab = {
    id: string
    position: number
    data: number
}

This comes in handy when you kind of want to make a few different types of types that inherit from kind of a base likes above examples

Let’s get into some more practical examples on react.

import React, { useState } from 'react';

type Props = {
    name: string
}
const HelloWorld: React.VFC<Props> = ({ name }) => {
    const [state] = useState<{ fullname: string | null }>({ fullname: "" })
    
    return <div>hello {name}</div>
}

// JSX generic
type FormProps<T> = {
    values: T;
    children: (values: T) => JSX.Element // A render prop
}
const Form = <T extends {}>({ values, children }: FormProps<T>) => {
    return children(values)
}

const App: React.VFC = () => (
    <div className="App">
        <Form<{ firstName: string | null }> values={{ firstName: "bob" }}>
            {(values) => <div>hello {values.firstName}</div>}
        </Form>
    </div>
)
export default App

At line 83: the angle brackets there is a case where react created type definitions or interfaces where they take a generic and their generic is what the props are because the props are going to be generic they don’t know ahead of time all the data that you want to pass into your component. So in this case we can say we want our component here to take a name and now we get type definition of the name there