-
Notifications
You must be signed in to change notification settings - Fork 39
Typescript: (3) Creating Generic Types
Mithi Sevilla edited this page Mar 30, 2021
·
1 revision
type Coordinate = [number,number, number]
const points: Coordinate[] = [
[1, 2, 3], [0, 0, 0], [4, 7, 90]
]
// Coordinate[] and Array<Coordinate>
// declarations are the same
const response: Promise<Response> = fetch("https://swapi.dev/api")
response.then(r => console.log(r.ok))
type Action = {
type: "fetchedName"
data: string
}
type ImmutableAction = Readonly<Action>
type Contact = {
name: string
email: string
}
type PartialContact = Partial<Contact>
/* equivalent to
type PartialContact = {
name?: string
email?: string
}
*/
type Result = {
score: number
total: number
}
type Username = "rodj" | "janes" | "fredp"
type ResultRecord = Record<Username, Result>
const finalResult: ResultRecord = {
rodj: {score: 80, total: 100 },
janes: {score: 80, total: 100 },
fredp: {score: 80, total: 100 },
}
type OptionalContact = { email?: string, name?: string }
type RequiredContact = Required<OptionalContact>
const bob: OptionalContact = {} // no error
const fred: RequiredContact = {}
// Type '{}' is missing the following properties from type 'Required<OptionalContact>': email, name
type ItemType = string | number
function firstOrNull<ItemType>(array: ItemType[]): ItemType | null {
return array.length === 0 ? null : array[0]
}
console.log(firstOrNull<string>(["Rod", "Jane", "Fred"]))
console.log(firstOrNull<number>([1, 71, 45]))
console.log(firstOrNull<number>([]))
IMPORTANT FOR ARROW FUNCTIONS
type ItemType = string | number
const findFirst = <ItemType, >(array: ItemType[], match: ItemType): ItemType | null => {
return array.indexOf(match) ===-1 ? null : array.filter(item => item === match)[0]
}
If you use <ItemType>
instead of <ItemType, >
This will error
'ItemType' only refers to a type, but is being used as a value here.
interface Form<T> {
values: T
}
interface Contact {
name: string
email: string
}
const contactForm: Form<Contact> = {
values: {
name: "Bob",
email: "[email protected]"
}
}
Add validation errors
interface Form<T> {
values: T,
errors: {
[P in keyof T]?: string
}
}
// [P in keyof T]
// puts keys in the type T into a string literal union
// ie:
// type T = "name" | "email"
// ? properties are optional
// type of errors will be:
// errors: {name?: string, email: string }
// errors is a requed property because it is not errors?: {...}
Example usage
const contactForm: Form<Contact> = {
errors: {
email: "Must be a valid email address"
},
values: {
name: "fred",
email: "doesnthaveEmailFormat"
}
}
- The code below will error because the generated type of the possible properties of
errors
is only"name" | "email"
. - This is from
[P in keyof T]
whereT
istype Contact = { name: string, email: string}
so[P in keyof T
are the keys ofContact
const contactForm: Form<Contact> = {
errors: {
age: "you must enter your age"
},
values: {
name: "fred",
email: "doesnthaveEmailFormat"
}
}
Here's the type alias version
// interface
interface Form<T> {
values: T,
errors: {
[P in keyof T]?: string
}
}
// type
type Form<T> = {
values: T,
errors: {
[P in keyof T]?: string
}
}
class List<ItemType> {
private items: ItemType[] = []
add(item: ItemType) {
this.items.push(item)
}
}
const numberList = new List<number>()
numberList.add(1)
// numberList.add(null) // this will error