Spec-Zone.ru › Flow

Непрозрачные псевдонимы типов

Непрозрачные псевдонимы типов — это псевдонимы типов, которые скрывают базовый тип за пределами файла, в котором они определены.

opaque type ID = string;
Сравнение с TypeScript

Непрозрачные типы доступны только в Flow — в TypeScript нет встроенного аналога. Распространённый идиоматический подход в TS — «брендированные типы» (пересечение с типизированным приватным символом свойством), то есть шаблон на пользовательском уровне, а не функция языка. Обеспечиваемая им граница слабее, чем абстракция с областью видимости файла в Flow: бренды TS реализуются на пользовательском уровне и могут быть подделаны с помощью приведения as, а также допускают структурное создание, если ключ бренда доступен или является строковым, а не приватным unique symbol. Полное сравнение см. в разделе Непрозрачные типы в Flow.

Когда это использовать​

Используйте непрозрачные типы вместо обычных псевдонимов типов, когда нужно обеспечить границы абстракции между модулями — например, запретить вызывающему коду рассматривать ID как обычный string. Обычный type ID = string прозрачен на границах файлов, поэтому любой потребитель может обращаться с ID в точности как с string; opaque type ID = string сохраняет эту прозрачность внутри файла, где он определён, но скрывает базовый тип на границе модуля.

exports.js

export type TransparentID = string;


export opaque type OpaqueID = string;
export function makeOpaqueID(s: string): OpaqueID { return s; }

imports.js

// The importer's view: `TransparentID` is still `string`; `OpaqueID` is nominal.
declare type TransparentID = string;
declare opaque type OpaqueID;
declare function makeOpaqueID(s: string): OpaqueID;


const a: TransparentID = "abc"; // Works — transparent alias is interchangeable with string
const b: string = a; // Works — round-trips with no boundary


const oid: OpaqueID = makeOpaqueID("abc"); // Works — the only way to obtain an OpaqueID
const c: OpaqueID = "abc"; // Error — outside the defining file, string is not an OpaqueID
const d: string = oid; // Error — outside the defining file, OpaqueID is not a string

Используйте opaque type, когда вызывающие стороны должны получать значение только через функцию-конструктор, контролируемую определяющим модулем, — например, для идентификаторов, очищенных строк или единиц измерения. Оставьте type, если псевдоним нужен только для документации и вас устраивает, что потребители будут обращаться с ним как с его базовым представлением. Используйте необязательное ограничение супертипа, если потребителям нужен частичный доступ (например, возможность читать ID как string, но не создавать его из string).

Синтаксис непрозрачных псевдонимов типов​

Непрозрачные псевдонимы типов создаются с помощью ключевых слов opaque type, за которыми следуют имя псевдонима, знак равенства = и определение типа.

opaque type Alias = Type;

К непрозрачному псевдониму типа можно добавить необязательное ограничение подтипизации: после имени укажите двоеточие : и тип.

opaque type Alias: SuperType = Type;

В качестве супертипа или типа непрозрачного псевдонима типа можно использовать любой тип.

opaque type StringAlias = string;
opaque type ObjectAlias = {
  property: string,
  method(): number,
};
opaque type UnionAlias = 1 | 2 | 3;
opaque type AliasAlias: ObjectAlias = ObjectAlias;
opaque type VeryOpaque: AliasAlias = ObjectAlias;

Проверка типов непрозрачных псевдонимов типов​

Внутри файла, где тип определён​

В том же файле, где определён псевдоним, непрозрачные псевдонимы типов ведут себя точно так же, как обычные псевдонимы типов.

opaque type NumberAlias = number;


0 as NumberAlias;


function add(x: NumberAlias, y: NumberAlias): NumberAlias {
    return x + y;
}
function toNumberAlias(x: number): NumberAlias { return x; }
function toNumber(x: NumberAlias): number { return x; }

За пределами файла, где тип определён​

При импорте непрозрачный псевдоним типа ведёт себя как номинальный тип, скрывая свой базовый тип.

exports.js

export opaque type NumberAlias = number;

imports.js

// In imports.js, NumberAlias is opaque — its underlying type (number) is hidden
declare opaque type NumberAlias;


0 as NumberAlias; // Error: 0 is not a NumberAlias!


function convert(x: NumberAlias): number {
  return x; // Error: x is not a number!
}

Ограничения подтипизации​

Если добавить к непрозрачному псевдониму типа ограничение подтипизации, за пределами файла, где он определён, непрозрачный тип можно использовать как супертип.

exports.js

export opaque type ID: string = string;

imports.js

// In imports.js, ID is opaque with a supertype constraint of string
declare opaque type ID: string;


function formatID(x: ID): string {
    return "ID: " + x; // OK! IDs are strings.
}


function toID(x: string): ID {
    return x; // Error: strings are not IDs.
}

При создании непрозрачного псевдонима типа с ограничением подтипизации тип в позиции типа должен быть подтипом типа в позиции супертипа.

opaque type Bad: string = number; // Error: number is not a subtype of string
opaque type Good: {x: string, ...} = {x: string, y: number};

Обобщённые типы​

У непрозрачных псевдонимов типов также могут быть собственные параметры типа, которые работают точно так же, как параметры типа у обычных псевдонимов типов

opaque type MyObject<A, B, C>: {foo: A, bar: B, ...} = {
  foo: A,
  bar: B,
  baz: C,
};


const val: MyObject<number, boolean, string> = {
  foo: 1,
  bar: true,
  baz: 'three',
};

Определения библиотек​

Непрозрачные псевдонимы типов также можно объявлять в определениях библиотек. В этом случае базовый тип не указывается, но супертип при желании можно добавить.

declare opaque type Foo;
declare opaque type PositiveNumber: number;

См. также​

  • Псевдонимы типов — обычные (прозрачные) псевдонимы типов
  • Номинальная и структурная типизация — непрозрачные типы типизируются номинально, в отличие от обычных псевдонимов типов
  • Обобщённые типы — непрозрачные псевдонимы типов можно параметризовать
  • Определения библиотек — объявление непрозрачных типов в файлах определений библиотек

© 2013–present Facebook Inc.
Licensed under the MIT License.
https://flow.org/en/docs/types/opaque-types

Spec-Zone.ru

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