Создание определений библиотек
Прежде чем тратить время на написание собственного libdef, мы рекомендуем проверить, не существует ли уже libdef для стороннего кода, с которым вы работаете. flow-typed — это инструмент и репозиторий для совместного использования стандартных libdef в сообществе Flow, поэтому это отличный способ закрыть значительную часть общедоступных libdef, которые могут понадобиться для вашего проекта.
Однако иногда готового libdef нет, либо у вас есть сторонний код, который не является публичным, и/или вам просто необходимо написать libdef самостоятельно. Для этого начните с создания файла .js для каждого libdef, который вы собираетесь написать, и поместите их в директорию /flow-typed в корне вашего проекта. В этих файлах libdef вы будете использовать специальный синтаксис Flow (описанный ниже) для описания интерфейсов соответствующего стороннего кода.
Объявление глобальной функции
Чтобы объявить глобальную функцию, которая должна быть доступна во всем проекте, используйте синтаксис declare function в файле libdef:
flow-typed/myLibDef.js
declare function foo(a: number): string;
Это сообщает Flow, что любой код в проекте может ссылаться на глобальную функцию foo, и что эта функция принимает один аргумент (number) и возвращает string.
Объявление глобального класса
Чтобы объявить глобальный класс, который должен быть доступен во всем проекте, используйте синтаксис declare class в файле libdef:
flow-typed/myLibDef.js
declare class URL {
constructor(urlStr: string): void;
toString(): string;
static compare(url1: URL, url2: URL): boolean;
} Это сообщает Flow, что любой код в проекте может ссылаться на глобальный класс URL. Обратите внимание, что это определение класса не содержит никаких деталей реализации — оно исключительно определяет интерфейс класса.
Объявление глобальной переменной
Чтобы объявить глобальную переменную, которая должна быть доступна во всем проекте, используйте синтаксис declare var, declare let или declare const в файле libdef:
flow-typed/myLibDef.js
declare const PI: number;
Это сообщает Flow, что любой код в проекте может ссылаться на глобальную переменную PI, которая в данном случае является number.
Объявление глобального типа
Чтобы объявить глобальный тип, который должен быть доступен во всем проекте, используйте синтаксис declare type в файле libdef:
flow-typed/myLibDef.js
declare type UserID = number;
Это сообщает Flow, что любой код в проекте может ссылаться на глобальный тип UserID, который в данном случае является просто псевдонимом для number.
Объявление глобального пространства имён
Пространство имён определяет набор значений и типов:
declare namespace Foo {
declare const bar: string;
type Baz = number;
}
Foo.bar as Foo.Baz; // error Чтобы объявить глобальное пространство имён, которое должно быть доступно во всем проекте, используйте синтаксис declare namespace в файле libdef:
flow-typed/myLibDef.js
declare namespace Foo {
declare const bar: string;
type Baz = number;
} Это сообщает Flow, что любой код в проекте может ссылаться на глобальное пространство имён Foo.
Если объявленное пространство имён содержит только объявления типов, то само пространство имён может использоваться только в контексте типов.
flow-typed/myTypeOnlyNamespace.js
declare namespace TypeOnlyFoo {
type Baz = number;
}
TypeOnlyFoo; // error
type T = TypeOnlyFoo.Baz; // ok Объявление модуля
Часто сторонний код организован в виде модулей, а не глобальных сущностей. Flow предлагает два различных способа объявления модуля.
Объявление модуля в директории @flowtyped
Flow поддерживает простое объявление сторонних модулей в директории @flowtyped в корне проекта. Перед тем как искать спецификатор модуля foo/bar/baz в node_modules, Flow выполнит поиск в @flowtyped/foo/bar/baz.js.flow и @flowtyped/foo/bar/baz/index.js.flow.
Например, если вы хотите объявить типы для react, вы можете сделать следующее:
@flowtyped/react.js.flow
export type SetStateFunction<S> = ((S => S) | S) => void; declare export function useState<S>(initial: S): [S, SetStateFunction<S>]; // Other stuff...
что позволит вам импортировать эти функции и типы из react:
foo/bar/baz/my-product-code.jsx
import * as React from 'react';
function MyComponent({onSelect}: {onSelect: React.SetStateFunction<string>}) {
const [a, setA] = React.useState(new Set<string>());
return <div />;
}
// Other stuff... Если вы хотите объявить типы для scoped-пакета, такого как @my-company/library-a, вы можете сделать следующее:
@flowtyped/@my-company/library-a.js.flow
declare export const foo: string; declare export const bar: number;
Если вы хотите объявить типы для глубоко вложенного модуля в пакете, такого как react-native/internals/foo, вы можете сделать следующее:
@flowtyped/react-native/internals/foo.js.flow
declare export const SECRET_INTERNALS_Foo: {...}; Этот подход предпочтительнее подхода, описанного ниже, поскольку редактирование этих файлов не вызывает перезапуск сервера Flow.
Объявление модуля в глобальном пространстве имён
Вы также можете объявлять модули с помощью синтаксиса declare module:
declare module "some-third-party-library" {
// This is where we'll list the module's exported interface(s)
} Имя, указанное в кавычках после declare module, может быть любой строкой, но оно должно соответствовать той же строке, которую вы бы использовали для require или import стороннего модуля в вашем проекте. Информацию об определении модулей, доступ к которым осуществляется по относительному пути require/import, см. в документации по файлам .flow.
В теле блока declare module вы можете указать набор экспортов для этого модуля. Однако прежде чем говорить об экспортах, необходимо рассмотреть два типа модулей, поддерживаемых Flow: CommonJS и ES-модули.
Flow может работать как с CommonJS, так и с ES-модулями, но между ними есть существенные различия, которые необходимо учитывать при использовании declare module.
Объявление модуля ES
ES-модули имеют два вида экспорта: именованный экспорт и экспорт по умолчанию. Flow поддерживает возможность объявления любого из этих видов экспорта или обоих сразу внутри тела declare module следующим образом:
Именованные экспорты
flow-typed/some-es-module.js
declare module "some-es-module" {
// Declares a named "concatPath" export
declare export function concatPath(dirA: string, dirB: string): string;
} Обратите внимание, что вы также можете объявлять и другие сущности внутри тела declare module, и область их видимости будет ограничена телом declare module — но они не будут экспортированы из модуля:
flow-typed/some-es-module.js
declare module "some-es-module" {
// Defines the type of a Path class within this `declare module` body, but
// does not export it. It can only be referenced by other things inside the
// body of this `declare module`
declare class Path {
toString(): string;
}
// Declares a named "concatPath" export which returns an instance of the
// `Path` class (defined above)
declare export function concatPath(dirA: string, dirB: string): Path;
} Экспорты по умолчанию
flow-typed/some-es-module.js
declare module "some-es-module" {
declare class URL {
constructor(urlStr: string): void;
toString(): string;
static compare(url1: URL, url2: URL): boolean;
}
// Declares a default export whose type is `typeof URL`
declare export default typeof URL;
} Также возможно объявлять как именованные экспорты, так и экспорт по умолчанию в одном и том же теле declare module.
Объявление модуля CommonJS
Модули CommonJS имеют одно экспортируемое значение (значение module.exports). Чтобы описать тип этого единственного значения внутри тела declare module, используйте синтаксис declare module.exports:
flow-typed/some-commonjs-module.js
declare module "some-commonjs-module" {
// The export of this module is an object with a "concatPath" method
declare module.exports: {
concatPath(dirA: string, dirB: string): string;
};
} Обратите внимание, что вы также можете объявлять и другие сущности внутри тела declare module, и область их видимости будет ограничена телом declare module, но они не будут экспортированы из модуля:
flow-typed/some-commonjs-module.js
declare module "some-commonjs-module" {
// Defines the type of a Path class within this `declare module` body, but
// does not export it. It can only be referenced by other things inside the
// body of this `declare module`
declare class Path {
toString(): string;
}
// The "concatPath" function now returns an instance of the `Path` class
// (defined above).
declare module.exports: {
concatPath(dirA: string, dirB: string): Path
};
} ПРИМЕЧАНИЕ: Поскольку модуль не может одновременно являться ES-модулем и модулем CommonJS, смешивание declare export [...] с declare module.exports: ... в одном и том же теле declare module считается ошибкой.
Слияние объявлений
Libdef должен определять данный модуль в одном блоке declare module 'name' { ... } — Flow не объединяет несколько блоков для одного и того же модуля; второй блок считается переопределением первого. Информацию об объединении, которое поддерживается — между интерфейсами, классами и пространствами имён — см. в разделе Слияние объявлений.
См. также
-
Файлы объявлений — альтернативный подход с использованием файлов
.flow - Типы модулей — как типы импортируются и экспортируются между модулями
© 2013–present Facebook Inc.
Licensed under the MIT License.
https://flow.org/en/docs/libdefs/creation