From f5b8f96130668b3840aed63bfc0b100950080373 Mon Sep 17 00:00:00 2001 From: jaywcjlove <398188662@qq.com> Date: Tue, 27 Sep 2022 10:56:10 +0800 Subject: [PATCH] feat: add `typescript` cheatsheet. --- README.md | 1 + docs/javascript.md | 2 + docs/typescript.md | 1237 ++++++++++++++++++++++++++++++++++++++++++++ scripts/style.css | 26 +- 4 files changed, 1264 insertions(+), 2 deletions(-) create mode 100644 docs/typescript.md diff --git a/README.md b/README.md index d8fef7a..b13bda1 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Quick Reference ## 编程 [TOML](./docs/toml.md) +[TypeScript](./docs/typescript.md) [JavaScript](./docs/javascript.md) [JSON](./docs/json.md) [Markdown](./docs/markdown.md) diff --git a/docs/javascript.md b/docs/javascript.md index 77e12aa..6953b83 100644 --- a/docs/javascript.md +++ b/docs/javascript.md @@ -12,6 +12,7 @@ JavaScript 是一种轻量级的解释型编程语言。 - [JSON 备忘清单](json.md) - [JavaScript 中的正则表达式](/regex#regex-in-javascript) +- [TypeScript 备忘清单](./typescript.md) ### 打印调试 @@ -29,6 +30,7 @@ console.error(new Error('Oops!')); ```javascript let amount = 6; let price = 4.99; +let home = 1e2; ``` ### 变量 diff --git a/docs/typescript.md b/docs/typescript.md new file mode 100644 index 0000000..31b38cb --- /dev/null +++ b/docs/typescript.md @@ -0,0 +1,1237 @@ +TypeScript 备忘清单 +=== + +包含最重要基础、泛型、方法、class 等 TypeScript 强类型编程语言语法的快速参考备忘单。初学者的完整快速参考。 + +入门 Interface +---- + +### 介绍 + +TypeScript 是具有类型语法的 JavaScript。Interface 是为了匹配它们的运行时行为而构建的。 + +- [JavaScript 备忘清单](./javascript.md) +- [TypeScript 官网](https://www.typescriptlang.org/) + +### 内置类型基元 + +```ts +boolean, string, number, +undefined, null, +any, unknown, never, +void, bigint, symbol +``` + +### 常见的内置 JS 对象 + +```ts +Date, Error, +Array, Map, Set, +Regexp, Promise +``` + +### 内置 + +#### 类型字面量 + +Object: + +```ts +{ field: string } +``` + +Function: + +```ts +(arg: number) => string +``` + +Arrays: + +```ts +string[] or Array +``` + +Tuple: + +```ts +[string, number] +``` + +#### 避免 + +``` +Object, String, Number, Boolean +``` + +### 通用语法 + + + +```ts +/** 可选择从现有接口或类型(Response, HTTPAble)中获取属性 */ +interface JSONResponse extends Response, HTTPAble { + version: number; + // 👇 附加在编辑器中显示的 JSDoc 注释 + /** In bytes */ + payloadSize: number; + // 👇 此属性可能不在对象上 + outOfStock?: boolean; + // 👇 这是描述作为函数的属性的两种方法 + update: (retryTimes: number) => void; + update(retryTimes: number): void; + // 👇 你可以通过 () 调用这个对象 -(JS中的函数是可以调用的对象) + (): JSONResponse + // 👇 您可以在此 Interface 描述的对象上使用 new + new(s: string): JSONResponse; + // 👇 任何未描述的属性都假定存在,并且所有属性必须是数字 + [key: string]: number; + // 👇 告诉 TypeScript 一个属性不能被改变 + readonly body: string; +} +``` + +### 泛型 + + +声明一个可以在你的 Interface 中改变的类型 + +```ts +interface APICall { + data: Response +} +``` + +#### 用法 + +```ts +const api: APICall = ... + +api.data // Artwork +``` + +您可以通过 `extends` 关键字限制泛型参数接受的类型。 + +```ts +interface APICall { + data: Response +} + +const api: APICall = ... + +api.data.status +``` + +### 重载 + +```ts +interface Expect { + (matcher: boolean): string + (matcher: string): boolean; +} +``` + +一个可调用 Interface 可以对不同的参数集有多个定义。 + +### 类一致性 + +```ts +interface Syncable { + sync(): void +} +class Account implements Syncable { ... } +``` + +您可以通过实现确保类 class 符合 Interface。 + +### Get & Set + +对象可以有自定义的 `getter` 或 `setter`。 + +```ts +interface Ruler { + get size(): number + set size(value: number | string); +} +``` + +用法 + +```ts +const r: Ruler = ... +r.size = 12 +r.size = "36" +``` + +### 通过合并扩展 + +```ts +interface APICall { + data: Response +} + +interface APICall { + error?: Error +} +``` + +Interface 被合并,多个声明将向类型定义添加新字段。 + +Type +---- + +### Type vs Interface + + +- Interface 只能描述对象形状 +- Interface 可以通过多次声明来扩展 +- 在性能关键 Type 中,Interface 比较检查可以更快。 + +#### 把类型想象成变量 + +就像您如何在不同范围内创建具有相同名称的变量一样,type 具有相似的语义。 + +#### 使用实用程序类型构建 + +TypeScript 包含许多全局类型,它们将帮助您在类型系统中完成常见任务。检查他们的网站。 + +### 原始类型 + +```ts +type SanitizedInput = string; +type MissingNo = 404; +``` + +主要用于文档 + +### 对象字面类型 + +```ts +type Location = { + x: number; + y: number; +}; +``` + +### 联合类型 + +```ts +type Size = "small" | "medium" | "large" +``` + +描述许多选项中的一个类型,例如已知字符串的列表。 + +### 交叉口类型 + +```ts +type Location = { x: number } + & { y: number } +// { x: number, y: number } +``` + +一种合并/扩展类型的方法 + +### 从值类型 + +```ts +const data = { ... } +type Data = typeof data +``` + +通过 typeof 运算符重用来自现有 JavaScript 运行时值的类型。 + + +### 从函数返回类型 + +```ts +const createFixtures = () => { ... } +type Fixtures = ReturnType +function test(fixture: Fixtures) {} +``` + +将函数的返回值重新用作类型。 + +### 从模块类型 + +```ts +const data: import("./data").data +``` + +这些功能非常适合构建库、描述现有的 JavaScript 代码,您可能会发现在大多数 TypeScript 应用程序中很少使用它们。 + +### 对象字面量语法 + + + +```ts +type JSONResponse = { + version: number; // 字段 + /** In bytes */ // 附加文档 + payloadSize: number; + outOfStock?: boolean; // 可选的 + update: (retryTimes: number) => void; // 箭头函数字段 + update(retryTimes: number): void; // 函数 + (): JSONResponse // 类型是可调用的 + [key: string]: number; // 接受任何索引 + new (s: string): JSONResponse; // new 对象 + readonly body: string; // 只读属性 +} +``` + +用于节省空间的 Terser,请参阅 Interface 备忘清单了解更多信息,除了“static”匹配之外的所有内容。 + +### 映射类型 + +```ts +type Artist = { + name: string, bio: string +} + +type Subscriber = { + [Property in keyof Type]: + (newValue: Type[Property]) => void +} +type ArtistSub = Subscriber +// { name: (nv: string) => +// void, bio: (nv: string) => void } +``` + +类似于类型系统的映射语句,允许输入类型更改新类型的结构。 + +### 模板联合类型 + + + +```ts +type SupportedLangs = "en" | "pt" | "zh"; +type FooterLocaleIDs = "header" | "footer"; +type AllLocaleIDs = `${SupportedLangs}_${FooterLocaleIDs}_id`; + +// "en_header_id" | "en_footer_id" +// | "pt_header_id" | "pt_footer_id" +// | "zh_header_id" | "zh_footer_id" +``` + +### 条件类型 + + + +```ts +type HasFourLegs = Animal extends { legs: 4 } ? Animal : never +type Animals = Bird | Dog | Ant | Wolf; +type FourLegs = HasFourLegs +// Dog | Wolf +``` + +在类型系统中充当“if 语句”。 通过泛型创建,然后通常用于减少类型联合中的选项数量。 + +控制流动分析 +---- + +### If 声明 + + +#### typeof(用于原语) + +```ts +const input = getUserInput() +input // string | number + +if (typeof input === 'string') { + input // string +} +``` + +#### 对象中的“property”(对于对象) + +```ts +const input = getUserInput() +input // string | { error: ... } + +if ('error' in input) { + input // { error: ... } +} +``` + +#### instanceof(用于类) + +```ts +const input = getUserInput() + input // number | number[] + +if (input instanceof Array) { + input // number[] +} +``` + +#### 类型保护功能(适用于任何东西) + +```ts +const input = getUserInput() + input // number | number[] + +if (Array.isArray(input)) { + input // number[] +} +``` + +### 任务 + + + +```ts +const data1 = { + name: "Zagreus" +} +// typeof data1 = { +// name: string +// } +``` + +使用 `as const` 缩小类型 + +```ts +const data2 = { + name: "Zagreus" +} as const +// typeof data1 = { +// name: 'Zagreus' +// } +``` + +跟踪相关变量 + +```ts +const response = getResponse() +const isSuccessResponse = + res instanceof SuccessResponse + +if (isSuccessResponse) { + res.data // SuccessResponse +} +``` + +重新分配更新类型 + +```ts +let data: string | number = ... +data // string | number +data = "Hello" +data // string +``` + +### 关键点 + +CFA 几乎总是采用联合,并根据代码中的逻辑减少联合内的类型数量。 + +大多数时候 CFA 在自然 JavaScript 布尔逻辑中工作,但是有一些方法可以定义您自己的函数,这些函数会影响 TypeScript 如何缩小类型。 + +### 表达式 + +```ts +const input = getUserInput() +input // string | number +const inputLength = + (typeof input === "string" && input.length) + || input + // input: string +``` + +在进行布尔运算时,缩窄也发生在与代码相同的行上 + +### 可识别联合 + +```ts +type Responses = + | { status: 200, data: any } + | { status: 301, to: string } + | { status: 400, error: Error } +``` + +#### 用法 + +```ts +const response = getResponse() +response // Responses +switch(response.status) { + case 200: return response.data + case 301: return redirect(response.to) + case 400: return response.error +} +``` + +### 断言函数 + +描述影响当前范围的 CFA 更改的函数,因为它抛出而不是返回 false。 + +```ts +function assertResponse(obj: any): + asserts obj is SuccessResponse { + if (!(obj instanceof SuccessResponse)) { + throw new Error('Not a success!') + } +} +``` + +#### 用法 + +```ts +const res = getResponse(): +res // SuccessResponse | ErrorResponse + +// 断言函数改变当前作用域或抛出 +assertResponse(res) + +res // SuccessResponse +``` + +Class +---- + +### 创建类实例 + +```ts +class ABC { ... } +const abc = new ABC() +``` + +新 ABC 的参数来自构造函数。 + +#### private x 与 #private + +前缀 private 是一个仅类型的添加,在运行时没有任何影响。 在以下情况下,类之外的代码可以进入项目: + +```ts +class Bag { + private item: any +} +``` + +Vs #private 是运行时私有的,并且在 JavaScript 引擎内部强制执行,它只能在类内部访问: + +```ts +class Bag { #item: any } +``` + +#### Class 上的 “this” + +函数内部‘this’的值取决于函数的调用方式。 不能保证始终是您可能在其他语言中使用的类实例。 + +您可以使用“此参数”、使用绑定功能或箭头功能来解决问题。 + +#### 类型和值 + +一个类既可以用作类型也可以用作值。 + +```ts +const a:Bag = new Bag() +``` + +所以,小心不要这样做: + +```ts +class C implements Bag {} +``` + +### 通用语法 + + + +```ts +// 确保类符合一组接口或类型 ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈▶┈┈╮ +// 子类这个类 ┈┈┈┈┈┈┈┈↘ ┈┈┈┈┈┈┈┈┈┈┈┈┈┴┈┈┈┈┈┈┈ +class User extends Account implements Updatable, Serializable { + id: string; // 一个字段 + displayName?: boolean; // 可选字段 + name!: string; // '相信我,它在哪里'字段 + #attributes: Map; // 私人字段 + roles = ["user"]; // 具有默认值的字段 + readonly createdAt = new Date() // 具有默认值的只读字段 + // 👇 代码调用“new” + constructor(id: string, email: string) { + super(id); + // 👇 在 `strict: true` 中,会根据字段检查此代码以确保其设置正确 + this.email = email; + // .... + }; + // 👇 描述类方法(和箭头函数字段)的方式 + setName(name: string) { this.name = name } + verifyName = (name: string) => { /* ... */ } + + // 👇 具有 2 个重载定义的函数 + sync(): Promise<{ ... }> + sync(cb: ((result: string) => void)): void + sync(cb?: ((result: string) => void)): void | Promise<{ ... }> {} + // 👇 Getters 和 setters + get accountID() { } + set accountID(value: string) { } + // 👇 私有访问只是对这个类,受保护的允许子类。 仅用于类型检查,public 是默认值。 + private makeRequest() { ... } + protected handleRequest() { ... } + // 👇 静态字段/方法 + static #userCount = 0; + static registerUser(user: User) { ... } + // 👇 用于设置静态变量的静态块。 ‘this’指的是静态类 + static { this.#userCount = -1 } +} +``` + +### 泛型 + +声明一个可以在你的类方法中改变的类型。 + +```ts +class Box { + contents: Type + constructor(value: Type) { + this.contents = value; + } +} +const stringBox = new Box("a package") +``` + +这些功能是 TypeScript 特定的语言扩展,可能永远无法使用当前语法进入 JavaScript。 + +### 参数属性 + +```ts +class Location { + constructor(public x: number, public y: number) {} +} +const loc = new Location(20, 40); + +loc.x // 20 +loc.y // 40 +``` + +TypeScript 特定于类的扩展,可自动将实例字段设置为输入参数。 + +### 抽象类 + +```ts +abstract class Animal { + abstract getName(): string; + printName() { + console.log("Hello, " + this.getName()); + } +} +class Dog extends Animal { getName(): { ... } } +``` + +一个类可以被声明为不可实现,但可以在类型系统中被子类化。 class 成员也可以。 + +### 装饰器和属性 + + + +```ts +import { Syncable, triggersSync, preferCache, required } from "mylib" + +@Syncable +class User { + @triggersSync() + save() { ... } + @preferCache(false) + get displayName() { ... } + update(@required info: Partial) { ... } +} +``` + +您可以在类、类方法、访问器、属性和方法参数上使用装饰器。 + +### 索引签名 + +```ts +class MyClass { + // 最好将索引数据存储在另一个地方 + // 而不是类实例本身。 + [s: string]: + boolean | ((s: string) => boolean); + + check(s: string) { + return this[s] as boolean; + } +} +``` + +类可以声明索引签名,与其他对象类型的索引签名相同。 + +实用程序类型 +---- + +### Awaited\ + +```ts +type A = Awaited>; +// type A = string + +type B = Awaited>>; +// type B = number + +type C = Awaited>; +// type C = number | boolean +``` + +这种类型旨在模拟异步函数中的 await 或 Promises 上的 .then() 方法等操作 - 特别是它们递归解包 Promises 的方式。 + +### Required\ + +```ts +interface Props { + a?: number; + b?: string; +} + +const obj: Props = { a: 5 }; +const obj2: Required = { a: 5 }; +// ❌ 类型“{ a: number;”中缺少属性“b” }' +// 但在 'Required' 类型中是必需的。 +``` + +使 Type 中的所有属性成为必需 + +### Readonly\ + +```ts +interface Todo { + title: string; +} +const todo: Readonly = { + title: "Delete inactive users", +}; +todo.title = "Hello"; +// ❌ 无法分配给“title”,因为它是只读属性。 + +function freeze(obj: Type) + : Readonly; +``` + +将 Type 中的所有属性设为**只读** + +### Partial\ + +```ts +interface Todo { + title: string; + description: string; +} +function updateTodo( + todo: Todo, + fieldsToUpdate: Partial +) { + return { ...todo, ...fieldsToUpdate }; +} +const todo1 = { + title: "organize desk", + description: "clear clutter", +}; +const todo2 = updateTodo(todo1, { + description: "throw out trash", +}); +``` + +将 `Type` 中的所有属性设为可选 + +### Record\ + +```ts +interface CatInfo { + age: number; + breed: string; +} + +type CatName = "miffy" | "boris"; +const cats: Record = { + miffy: {age:10, breed: "Persian" }, + boris: {age:5, breed: "Maine Coon" }, +}; + +cats.boris; +// 👉 const cats: Record +``` + +构造一个具有一组 Keys 类型的属性 Type 的类型 + +### Pick\ + +```ts +interface Todo { + name: string; + description: string; + completed: boolean; +} +type TodoPreview = Pick< + Todo, "name" | "load" +>; +const todo: TodoPreview = { + name: "Clean room", + load: false, +}; + +todo; + // 👉 const todo: TodoPreview +``` + +从 Type 中**选择**一组其键在并集 Keys 中的属性 + +### Exclude\ + +```ts +type T0 = Exclude<"a" | "b" | "c", "a">; +// 👉 type T0 = "b" | "c" + +type T1 = Exclude<"a"|"b"|"c", "a" | "b">; +// 👉 type T1 = "c" + +type T2 = Exclude void), Function>; +// 👉 type T2 = string | number +``` + +从 `UnionType` 中**排除**那些可分配给 `ExcludedMembers` 的类型 + +### Extract\ + +```ts +type T0 = Extract< + "a" | "b" | "c", "a" | "f" +>; +// type T0 = "a" +type T1 = Extract< + string | number | (() => void), + Function +>; +// type T1 = () => void +``` + +通过从 Type 中**提取**所有可分配给 Union 的联合成员来构造一个类型。 + +### NonNullable\ + +```ts +type T0 = NonNullable< + string | number | undefined +>; +// type T0 = string | number + +type T1 = NonNullable< + string[] | null | undefined +>; +// type T1 = string[] +``` + +通过从 Type 中**排除** null 和 undefined 来构造一个类型。 + +### Omit\ + +```ts +interface Todo { + name: string; + completed: boolean; + createdAt: number; +} + +type TodoPreview = Omit; + +const todo: TodoPreview = { + completed: false, + createdAt: 1615544252770, +}; + +todo; + // 👉 const todo: TodoPreview +``` + +构造一个具有 Type 属性的类型,但类型 Keys 中的属性**除外**。 + +### Parameters\ + +```ts +declare function f1( + arg: { a: number; b: string } +): void; + +type T0 = Parameters<() => string>; +// type T0 = [] +type T1 = Parameters<(s: string) => void>; +// type T1 = [s: string] +type T2 = Parameters<(arg: T) => T>; +// type T2 = [arg: unknown] +type T3 = Parameters; +// type T3 = [arg: { +// a: number; +// b: string; +// }] +type T4 = Parameters; +// type T4 = unknown[] +type T5 = Parameters; +// type T5 = never +``` + +从函数类型 Type 的**参数中**使用的类型构造元组类型。 + +### ConstructorParameters\ + +```ts +type T0 = ConstructorParameters< + ErrorConstructor +>; +// type T0 = [message?: string] +type T1 = ConstructorParameters< + FunctionConstructor +>; +// type T1 = string[] +type T2 = ConstructorParameters< + RegExpConstructor +>; +// type T2 = [ +// pattern: string | RegExp, +// flags?: string +// ] +type T3 = ConstructorParameters; +// type T3 = unknown[] +``` + +从构造函数类型的类型构造元组或数组类型。它产生一个包含所有参数类型的元组类型(如果 Type 不是函数,则类型 never )。 + +### 内在字符串操作类型 + +#### Uppercase\ + +```ts +type Greeting = "Hello, world" +type ShoutyGreeting = Uppercase +// type ShoutyGreeting = "HELLO, WORLD" + +type ASCIICacheKey = `ID-${Uppercase}` +type MainID = ASCIICacheKey<"my_app"> +// type MainID = "ID-MY_APP" +``` + +将字符串中的每个字符**转换为大写**版本。 + +#### Lowercase\ + +```ts +type Greeting = "Hello, world" +type QuietGreeting = Lowercase +// type QuietGreeting = "hello, world" + +type ASCIICacheKey = `id-${Lowercase}` +type MainID = ASCIICacheKey<"MY_APP"> +// type MainID = "id-my_app" +``` + +将字符串中的每个字符转换为等效的**小写字母**。 + +#### Capitalize\ + +```ts +type LowercaseGreeting = "hello, world"; +type Greeting = Capitalize; +// type Greeting = "Hello, world" +``` + +将字符串中的第一个字符转换为等效的**大写字母**。 + +#### Uncapitalize\ + +```ts +type UppercaseGreeting = "HELLO WORLD"; +type UncomfortableGreeting = Uncapitalize; +// type UncomfortableGreeting = "hELLO WORLD" +``` + +将字符串中的第一个字符转换为等效的**小写字母**。 + +### ReturnType\ + +```ts +declare function f1(): { + a: number; b: string +}; + +type T0 = ReturnType<() => string>; +// type T0 = string + +type T1 = ReturnType<(s: string) => void>; +// type T1 = void + +type T2 = ReturnType<() => T>; +// type T2 = unknown + +type T3 = ReturnType<< + T extends U, U extends number[] +>() => T>; +// type T3 = number[] + +type T4 = ReturnType; +// type T4 = { +// a: number; +// b: string; +// } + +type T5 = ReturnType; +// type T5 = any + +type T6 = ReturnType; +// type T6 = never +``` + +构造一个由函数 Type 的**返回类型**组成的类型。 + +### ThisType\ + +```ts +type ObjectDescriptor = { + data?: D; + // 方法中“this”的类型是 D & M + methods?: M & ThisType; +}; + +function makeObject( + desc: ObjectDescriptor +): D & M { + let data: object = desc.data || {}; + let methods: object = desc.methods || {}; + return { ...data, ...methods } as D & M; +} + +let obj = makeObject({ + data: { x: 0, y: 0 }, + methods: { + moveBy(dx: number, dy: number) { + this.x += dx; // Strongly typed this + this.y += dy; // Strongly typed this + }, + }, +}); + +obj.x = 10; +obj.y = 20; +obj.moveBy(5, 5); +``` + +此实用程序不返回转换后的类型。 相反,它用作上下文 this 类型的标记。 请注意,必须启用 [noImplicitThis](https://www.typescriptlang.org/tsconfig#noImplicitThis) 标志才能使用此实用程序。 + +### InstanceType\ + +```ts +class C { + x = 0; + y = 0; +} +type T0 = InstanceType; +// type T0 = C +type T1 = InstanceType; +// type T1 = any +type T2 = InstanceType; +// type T2 = never +``` + +构造一个由 Type 中构造函数的实例类型组成的类型。 + +### ThisParameterType\ + +```ts +function toHex(this: Number) { + return this.toString(16); +} + +function numberToString( + n: ThisParameterType +) { + return toHex.apply(n); +} +``` + +提取函数类型的 `this` 参数的类型,如果函数类型没有 `this` 参数,则为未知。 + +### OmitThisParameter\ + +```ts +function toHex(this: Number) { + return this.toString(16); +} +const fiveToHex + : OmitThisParameter + = toHex.bind(5); + +console.log(fiveToHex()); +``` + +从 Type 中移除 this 参数。 如果 Type 没有显式声明此参数,则结果只是 Type。 否则,从 Type 创建一个不带此参数的新函数类型。 泛型被删除,只有最后一个重载签名被传播到新的函数类型中。 + + +JSX +---- + + +### JSX 介绍 + +JSX 规范是对 ECMAScript 的类似 XML 的语法扩展。 + +- 使用 `.tsx` 扩展名命名您的文件 +- 启用 `jsx` 选项 +- 不允许在 `.tsx` 文件中使用尖括号类型断言。 +- [JSX 规范](https://facebook.github.io/jsx/) + +### as 运算符 + +```ts +const foo = bar; +// 不允许在 .tsx 👆 文件中使用尖括号类型断言。 + +const foo = bar as foo; +``` + +`as` 运算符在 `.ts` 和 `.tsx` 文件中都可用,并且在行为上与**尖括号**类型断言样式相同。 + +### 基于值的元素 + +```tsx +import MyComponent from "./myComponent"; + +; // ok +; // ❌ error +``` + +基于值的元素只是由范围内的标识符查找。 + +### 内在的元素 + +```tsx +declare namespace JSX { + interface IntrinsicElements { + foo: any; + } +} +; // ok +; // error +``` + +\ 没有在 JSX.IntrinsicElements 上指定。 + +```tsx +declare namespace JSX { + interface IntrinsicElements { + [elemName: string]: any; + } +} +``` + +### 函数组件 + + + +```tsx +interface FooProp { + name: string; + X: number; + Y: number; +} +declare function AnotherComponent(prop: { name: string }); +function ComponentFoo(prop: FooProp) { + return ; +} + +const Button = (prop: { value: string }, context: { color: string }) => ( +