UNPKG

mapbox-gl

Version:
127 lines (113 loc) 3.77 kB
// @flow export type NullTypeT = { kind: 'null' }; export type NumberTypeT = { kind: 'number' }; export type StringTypeT = { kind: 'string' }; export type BooleanTypeT = { kind: 'boolean' }; export type ColorTypeT = { kind: 'color' }; export type ObjectTypeT = { kind: 'object' }; export type ValueTypeT = { kind: 'value' }; export type ErrorTypeT = { kind: 'error' }; export type CollatorTypeT = { kind: 'collator' }; export type FormattedTypeT = { kind: 'formatted' }; export type ResolvedImageTypeT = { kind: 'resolvedImage' }; export type EvaluationKind = 'constant' | 'source' | 'camera' | 'composite'; export type Type = NullTypeT | NumberTypeT | StringTypeT | BooleanTypeT | ColorTypeT | ObjectTypeT | ValueTypeT | ArrayType | // eslint-disable-line no-use-before-define ErrorTypeT | CollatorTypeT | FormattedTypeT | ResolvedImageTypeT export type ArrayType = { kind: 'array', itemType: Type, N: ?number } export type NativeType = 'number' | 'string' | 'boolean' | 'null' | 'array' | 'object' export const NullType = {kind: 'null'}; export const NumberType = {kind: 'number'}; export const StringType = {kind: 'string'}; export const BooleanType = {kind: 'boolean'}; export const ColorType = {kind: 'color'}; export const ObjectType = {kind: 'object'}; export const ValueType = {kind: 'value'}; export const ErrorType = {kind: 'error'}; export const CollatorType = {kind: 'collator'}; export const FormattedType = {kind: 'formatted'}; export const ResolvedImageType = {kind: 'resolvedImage'}; export function array(itemType: Type, N: ?number): ArrayType { return { kind: 'array', itemType, N }; } export function toString(type: Type): string { if (type.kind === 'array') { const itemType = toString(type.itemType); return typeof type.N === 'number' ? `array<${itemType}, ${type.N}>` : type.itemType.kind === 'value' ? 'array' : `array<${itemType}>`; } else { return type.kind; } } const valueMemberTypes = [ NullType, NumberType, StringType, BooleanType, ColorType, FormattedType, ObjectType, array(ValueType), ResolvedImageType ]; /** * Returns null if `t` is a subtype of `expected`; otherwise returns an * error message. * @private */ export function checkSubtype(expected: Type, t: Type): ?string { if (t.kind === 'error') { // Error is a subtype of every type return null; } else if (expected.kind === 'array') { if (t.kind === 'array' && ((t.N === 0 && t.itemType.kind === 'value') || !checkSubtype(expected.itemType, t.itemType)) && (typeof expected.N !== 'number' || expected.N === t.N)) { return null; } } else if (expected.kind === t.kind) { return null; } else if (expected.kind === 'value') { for (const memberType of valueMemberTypes) { if (!checkSubtype(memberType, t)) { return null; } } } return `Expected ${toString(expected)} but found ${toString(t)} instead.`; } export function isValidType(provided: Type, allowedTypes: Array<Type>): boolean { return allowedTypes.some(t => t.kind === provided.kind); } export function isValidNativeType(provided: any, allowedTypes: Array<NativeType>): boolean { return allowedTypes.some(t => { if (t === 'null') { return provided === null; } else if (t === 'array') { return Array.isArray(provided); } else if (t === 'object') { return provided && !Array.isArray(provided) && typeof provided === 'object'; } else { return t === typeof provided; } }); }