Spec-Zone.ru › Flow

Создание определений библиотек

Прежде чем тратить время на написание собственного 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API