@haixing_hu/typeinfo
v3.1.2
Published
A JavaScript library provides a type information detection function
Readme
typeinfo
typeinfo 是一个轻量级的JavaScript库,它扩展了typeof操作符的功能,允许获取
JavaScript 变量更精确可靠的类型信息。它为最新的 ECMAScript 标准提供了增强支持,并为您的项目
中的类型识别提供了全面的解决方案。
Table of Contents
特性
- 对JavaScript变量提供准确的类型信息。
- 支持最新的ECMAScript标准。
- 易于集成到您的项目中。
安装
您可以通过 npm 安装 typeinfo:
npm install @haixing_hu/typeinfo或者通过 yarn 安装:
yarn add @haixing_hu/typeinfo例子
下面是一个使用示例:
import typeInfo from '@haixing_hu/typeinfo';
function clone(value) {
const info = typeInfo(value);
switch (info.type) {
case 'undefined': // drop down
case 'null': // drop down
case 'boolean': // drop down
case 'number': // drop down
case 'string': // drop down
case 'symbol': // drop down
case 'bigint': // drop down
case 'function': // drop down
return value; // don't need to clone immutable objects
case 'object': // drop down
default:
switch (info.subtype) {
case 'Boolean': // drop down
case 'Number': // drop down
case 'String': // drop down
return value; // don't need to clone immutable objects
case 'Date':
return new Date(value);
case 'RegExp':
return new RegExp(value);
...
}
}
}或者使用 info.category 简化代码逻辑:
import typeInfo from '@haixing_hu/typeinfo';
function clone(value) {
const info = typeInfo(value);
switch (info.category) {
case 'undefined': // drop down
case 'null': // drop down
case 'primitive': // drop down
case 'function':
return value; // don't need to clone immutable objects
case 'primitive-wrapper':
return value; // don't need to clone immutable objects
case 'date':
return new Date(value);
case 'regexp':
return new RegExp(value);
...
}
}使用
该库提供以下函数:
function typeInfo(value)- 参数:
value: any:指定的值。
- 返回值:
object:关于指定值类型的信息。
这个函数返回关于指定值的精确类型信息。返回的信息是一个具有以下属性的对象:
type: string: 指定值的类型名称。这与内置的typeof操作符返回的值相同,不同的是null值的类型是'null'而不是'object',并且我们增加了'global'表示 [global object] 的类型。subtype: string: 指定值的子类型名称。此属性仅在指定值的类型为'object'或'function'时存在。category: string:指定值的类别。这个属性适用于所有类型的值。更多详情请见Category。isPrimitive: boolean: 是否为原始值。isBuiltIn: boolean: 是否为JavaScript内置的原始值或内置对象。constructor: function: 指定值的构造函数。此属性仅在指定值的类型为'object'时存在。
Type
由 typeInfo() 返回的类型信息对象具有一个 type 属性,它可能具有以下值:
'undefined': 如果值为undefined。'null': 如果值为null。'boolean': 如果值为原始布尔值。'number': 如果值为原始数值。'string': 如果值为原始字符串值。'symbol': 如果值为符号值。'bigint': 如果值为原始bigint值。'function': 如果值为函数。'object': 如果值为普通对象。
type 属性的值类似于内置的 typeof 操作符返回的值,不同之处在于 null 的类型是 'null'
而不是 'object'。
Subtype
如果值的类型为function或object,typeInfo()返回的类型信息对象将包含subtype属性,
它是指定值的详细子类型名称。
'function'类型的可能subtype名称包括:
'Function': 如果值为同步函数。'GeneratorFunction': 如果值为同步生成器函数。'AsyncFunction': 如果值为异步函数。'AsyncGeneratorFunction': 如果值为异步生成器函数。
请注意,'AsyncFunction'和'AsyncGeneratorFunction'子类型只在支持异步函数的
JavaScript 引擎中可用。
'object'类型的可能subtype名称包括:
'Boolean': 如果值为JavaScript内置的Boolean对象。'Number': 如果值为JavaScript内置的Number对象。'String': 如果值为JavaScript内置的String对象。'RegExp': 如果值为正则表达式,即JavaScript内置的RegExp对象。'Date': 如果值为JavaScript内置的Date对象。'Map': 如果值为JavaScript内置的Map对象。'WeakMap': 如果值为JavaScript内置的WeakMap对象。'Set': 如果值为JavaScript内置的Set对象。'WeakSet': 如果值为JavaScript内置的WeakSet对象。'Array': 如果值为JavaScript内置的Array对象。'Int8Array': 如果值为JavaScript内置的Int8Array对象。'Uint8Array': 如果值为JavaScript内置的Uint8Array对象。'Uint8ClampedArray': 如果值为JavaScript内置的Uint8ClampedArray对象。'Int16Array': 如果值为JavaScript内置的Int16Array对象。'Uint16Array': 如果值为JavaScript内置的Uint16Array对象。'Int32Array': 如果值为JavaScript内置的Int32Array对象。'Uint32Array': 如果值为JavaScript内置的Uint32Array对象。'BigInt64Array': 如果值为JavaScript内置的BigInt64Array对象。'BigUint64Array': 如果值为JavaScript内置的BigUint64Array对象。'Float32Array': 如果值为JavaScript内置的Float32Array对象。'Float64Array': 如果值为JavaScript内置的Float64Array对象。'ArrayBuffer': 如果值为JavaScript内置的ArrayBuffer对象。'SharedArrayBuffer': 如果值为JavaScript内置的SharedArrayBuffer对象。'DataView': 如果值为JavaScript内置的DataView对象。'WeakRef': 如果值为JavaScript内置的WeakRef对象。'Promise': 如果值为JavaScript内置的Promise对象。'Error':如果值为JavaScript内置Error类的对象。'EvalError':如果值为JavaScript内置EvalError类的对象。'RangeError':如果值为JavaScript内置RangeError类的对象。'ReferenceError':如果值为JavaScript内置ReferenceError类的对象。'SyntaxError':如果值为JavaScript内置SyntaxError类的对象。'TypeError':如果值为JavaScript内置TypeError类的对象。'URIError':如果值为JavaScript内置URIError类的对象。'AggregateError':如果值为JavaScript内置AggregateError类的对象。'InternalError':如果值为JavaScript内置InternalError类的对象。'Intl.Collator': 如果值为JavaScript内置的Intl.Collator对象。'Intl.DateTimeFormat': 如果值为JavaScript内置的Intl.DateTimeFormat对象。'Intl.DisplayNames': 如果值为JavaScript内置的Intl.DisplayNames对象。'Intl.DurationFormat': 如果值为JavaScript内置的Intl.DurationFormat对象。'Intl.ListFormat': 如果值为JavaScript内置的Intl.ListFormat对象。'Intl.Locale': 如果值为JavaScript内置的Intl.Locale对象。'Intl.NumberFormat': 如果值为JavaScript内置的Intl.NumberFormat对象。'Intl.PluralRules': 如果值为JavaScript内置的Intl.PluralRules对象。'Intl.RelativeTimeFormat': 如果值为JavaScript内置的Intl.RelativeTimeFormat对象。'Intl.Segmenter': 如果值为JavaScript内置的Intl.Segmenter对象。'MapIterator': 如果值为由以下函数返回的映射对象Map的迭代器,:Map.prototype.values()Map.prototype.keys()Map.prototype.entries()Map.prototype[@@iterator]()
'SetIterator': 如果值为由以下函数返回的集合对象Set的迭代器:Set.prototype.values()Set.prototype.keys()Set.prototype.entries()Set.prototype[@@iterator]()
'ArrayIterator': 如果值为由以下函数返回的数组对象Array的迭代器:Array.prototype.values()Array.prototype.keys()Array.prototype.entries()Array.prototype[@@iterator]()TypedArray.prototype.values()TypedArray.prototype.keys()TypedArray.prototype.entries()
'StringIterator': 如果值为由以下函数返回的字符串对象String的迭代器:String.prototype[@@iterator]()
'RegExpStringIterator': 如果值为由以下函数返回的正则表达式对象RegExp的字符串迭代器:RegExp.prototype[@@matchAll]()String.prototype.matchAll()
'SegmenterStringIterator': 如果值为由以下函数返回的分段对象Intel.Segmenter的字 符串迭代器:Intl.Segmenter.prototype.segment()返回的Segments对象的[@@iterator]()方法。
'FinalizationRegistry': 如果值为JavaScript内置的FinalizationRegistry类的对象。 一个FinalizationRegistry对象允许您在一个值被垃圾收集时执行一个回调函数。'Arguments': 如果值为JavaScript内置的arguments对象;这是一个特殊的类数组对象,存储函数的调用参数。'Generator': 如果值为生成器对象,即同步生成器函数返回的对象。'AsyncGenerator': 如果值为异步生成器对象,即异步生成器函数返回的对象。'GlobalObject': 如果值为全局对象。全局对象是始终存在于全局作用域中的对象。'Object': 如果值为简单的 JavaScript 对象,即通过obj = { .. }语法定义的对象。''(空字符串): 如果值为用户定义的匿名类的实例。value[Symbol.toStringTag]: 如果值有自定义的Symbol.toStringTag属性。value.constructor.name: 如果值有具有名称的构造函数,并且名称不是'Object'。 也就是说,如果值为用户定义的类的实例,并且该类有名称,则subtype为该类的名称。- 从
value.toString()中提取的名称:如果值与上述任何情况都不匹配,则subtype是从value.toString()结果中提取的名称(通常为'[object XXX]'的形式), 并删除名称中的任何内部空格。例如,如果value.toString()结果为'[object My Class ]', 则subtype为'MyClass'。
该函数支持的JavaScript内置对象的详细列表可在 Standard built-in objects 中找到。
Category
typeInfo() 返回的类型信息对象具有一个 category 属性,它是指定值的类别。
category属性的可能值包括:
'null':如果值为null。'undefined':如果值为undefined。'boolean': 若指定的值为 primitiveboolean值,或内置的Boolean对象。'numeric': 若指定的值为 primitivenumber值,或 primitivebigint值,或内置的Number对象。'string': 若指定的值为 primitivestring值,或内置的String对象。'symbol': 若指定的值为 primitiveSymbol值,或内置的Boolean对象。'function':如果值为函数,包括同步函数、异步函数、同步生成器函数和异步生成器函数。'regexp':如果值为正则表达式,即JavaScript内置的RegExp对象。'date':如果值为JavaScript内置的Date对象。'map':如果值为JavaScript内置的Map对象。'set':如果值为JavaScript内置的Set对象。'array':如果值为JavaScript内置的Array对象。'typed-array':如果值为JavaScript内置的类型化数组对象,包括'Int8Array'、'Uint8Array'、'Uint8ClampedArray'、'Int16Array'、'Uint16Array'、'Int32Array'、'Uint32Array'、'BigInt64Array'、'BigUint64Array'、'Float32Array'和'Float64Array'。'buffer':如果值为JavaScript内置的缓冲区对象,包括'ArrayBuffer'和'SharedArrayBuffer'。'data-view':如果值为JavaScript内置的DataView对象。'weak':如果值为JavaScript内置的WeakMap,WeakSetorWeakRef对象。注意, 弱引用对象不可被克隆。'promise':如果值为JavaScript内置的Promise对象。'error':如果值为JavaScript内置的Error类的对象,或Error类的子类的对象。'intl':如果值为JavaScript内置的Intl命名空间下的对象,包括'Intl.Collator'、'Intl.DateTimeFormat'、'Intl.DisplayNames'、'Intl.DurationFormat'、'Intl.ListFormat'、'Intl.Locale'、'Intl.NumberFormat'、'Intl.PluralRules'和'Intl.RelativeTimeFormat'。'iterator':如果值为迭代器对象,包括'MapIterator'、'SetIterator'、'ArrayIterator'、'StringIterator'、'RegExpStringIterator'和'SegmenterStringIterator'。'finalization-registry':如果值为JavaScript内置的FinalizationRegistry类的实例。FinalizationRegistry对象允许您在值被垃圾回收时请求回调。'global':如果值为全局对象。'arguments':如果值为JavaScript内置的arguments对象。'DOM': 如果值为DOM对象,包括'Node'、'Element'、'Document'、'Window'等。'CSSOM': 如果值为CSSOM对象,包括'CSSStyleDeclaration'、'CSSRule'、'CSSStyleSheet'等。'event': 如果值为事件对象,包括'Event'、'MouseEvent'、'KeyboardEvent'等。'console': 如果值为控制台对象,即'window.console'。'file': 如果值为文件对象,包括'File'、'FileList'、'FileReader'等。'generator':如果值为生成器对象,即由同步生成器函数返回的对象,包括'Generator'和'AsyncGenerator'。'object':如果值为普通的JavaScript对象。'class':如果值为用户定义类的实例。
特性检测常量
此库提供以下常量用于 JavaScript 引擎的特性检测:
AGGREGATEERROR_EXISTS:JavaScript 内置类AggregateError是否存在。ARRAYBUFFER_EXISTS:JavaScript 内置类ArrayBuffer是否存在。ARRAY_ISARRAY_EXISTS:JavaScript 内置函数Array.isArray()是否存在。ARRAY_ITERATOR_EXISTS:JavaScript 内置函数Array.prototype[Symbol.iterator]是否存在。ATOMICS_EXISTS:JavaScript 内置对象Atomics是否存在。BIGINT64ARRAY_EXISTS:JavaScript 内置类BigInt64Array是否存在。BIGINT_EXISTS:JavaScript 内置原始类型bigint和内置函数BigInt是否存在。BIGUINT64ARRAY_EXISTS:JavaScript 内置类BigUint64Array是否存在。DATAVIEW_EXISTS:JavaScript 内置类DataView是否存在。FINALIZATIONREGISTRY_EXISTS:JavaScript 内置类FinalizationRegistry是否存在。FLOAT32ARRAY_EXISTS:JavaScript 内置类Float32Array是否存在。FLOAT64ARRAY_EXISTS:JavaScript 内置类Float64Array是否存在。INT16ARRAY_EXISTS:JavaScript 内置类Int16Array是否存在。INT32ARRAY_EXISTS:JavaScript 内置类Int32Array是否存在。INT8ARRAY_EXISTS:JavaScript 内置类Int8Array是否存在。INTERNALERROR_EXISTS:JavaScript 内置类InternalError是否存在。INTL_COLLATOR_EXISTS:JavaScript 内置类Intl.Collator是否存在。INTL_DATETIMEFORMAT_EXISTS:JavaScript 内置类Intl.DateTimeFormat是否存在。INTL_DISPLAYNAMES_EXISTS:JavaScript 内置类Intl.DisplayNames是否存在。INTL_DURATIONFORMAT_EXISTS:JavaScript 内置类Intl.DurationFormat是否存在。INTL_EXISTS:JavaScript 内置Intl命名空间是否存在。INTL_LISTFORMAT_EXISTS:JavaScript 内置类Intl.ListFormat是否存在。INTL_LOCALE_EXISTS:JavaScript 内置类Intl.Locale是否存在。INTL_NUMBERFORMAT_EXISTS:JavaScript 内置类Intl.NumberFormat是否存在。INTL_PLURALRULES_EXISTS:JavaScript 内置类Intl.PluralRules是否存在。INTL_RELATIVETIMEFORMAT_EXISTS:JavaScript 内置类Intl.RelativeTimeFormat是否存在。INTL_SEGMENTER_EXISTS:JavaScript 内置类Intl.Segmenter是否存在。INTL_SEGMENTER_ITERATOR_EXISTS:JavaScript 内置函数Intl.Segmenter.prototype[Symbol.iterator]是否存在。MAP_ENTRIES_EXISTS:JavaScript 内置函数Map.prototype.entries()是否存在。MAP_EXISTS:JavaScript 内置类Map是否存在。MAP_ITERATOR_EXISTS:JavaScript 内置函数Map.prototype[Symbol.iterator]是否存在。PROMISE_EXISTS:JavaScript 内置类Promise是否存在。PROXY_EXISTS:JavaScript 内置类Proxy是否存在。REFLECT_EXISTS:JavaScript 内置命名空间Reflect是否存在。REGEXP_EXISTS:JavaScript 内置类RegExp是否存在。REGEXP_ITERATOR_EXISTS:JavaScript 内置函数RegExp.prototype[Symbol.matchAll]是否存在。SET_ENTRIES_EXISTS:JavaScript 内置函数Set.prototype.entries()是否存在。SET_EXISTS:JavaScript 内置类Set是否存在。SET_ITERATOR_EXISTS:JavaScript 内置函数Set.prototype[Symbol.iterator]是否存在。SHAREDARRAYBUFFER_EXISTS:JavaScript 内置类SharedArrayBuffer是否存在。STRING_ITERATOR_EXISTS:JavaScript 内置函数String.prototype[Symbol.iterator]是否存在。SYMBOL_EXISTS:JavaScript 内置Symbol是否存在。SYMBOL_ITERATOR_EXISTS:JavaScript 内置函数Symbol.prototype[Symbol.iterator]是否存在。SYMBOL_MATCH_ALL_EXISTS:JavaScript 内置函数Symbol.prototype[Symbol.matchAll]是否存在。SYMBOL_TO_STRING_TAG_EXISTS:JavaScript 内置函数Symbol.prototype[Symbol.toStringTag]是否存在。UINT16ARRAY_EXISTS:JavaScript 内置类Uint16Array是否存在。UINT32ARRAY_EXISTS:JavaScript 内置类Uint32Array是否存在。UINT8ARRAY_EXISTS:JavaScript 内置类Uint8Array是否存在。UINT8CLAMPEDARRAY_EXISTS:JavaScript 内置类Uint8ClampedArray是否存在。WEAKMAP_EXISTS:JavaScript 内置类WeakMap是否存在。WEAKREF_EXISTS:JavaScript 内置类WeakRef是否存在。WEAKSET_EXISTS:JavaScript 内置类WeakSet是否存在。
以下代码展示如何使用这些常量:
import { WEAKMAP_EXISTS } from '@haixing_hu/typeinfo';
function foo(value) {
if (WEAKMAP_EXISTS) {
...
} else {
...
}
}类型原型常量
这个库为 JavaScript 内建对象的原型提供了以下常量:
AggregateErrorPrototype:JavaScript内建AggregateError对象的原型,如果AggregateError类不存在,则为undefined。ArrayBufferPrototype:JavaScript内建ArrayBuffer对象的原型,如果ArrayBuffer类不存在,则为undefined。ArrayIteratorPrototype:JavaScript内建数组迭代器对象的原型,如果数组迭代器不存在,则为undefined。BigInt64ArrayPrototype:JavaScript内建BigInt64Array对象的原型,如果BigInt64Array类不存在,则为undefined。BigIntPrototype:JavaScript内建bigint基本类型的原型,如果bigint基本类型不存在,则为undefined。BigUint64ArrayPrototype:JavaScript内建BigUint64Array对象的原型,如果BigUint64Array类不存在,则为undefined。DataViewPrototype:JavaScript内建DataView对象的原型,如果DataView类不存在,则为undefined。FinalizationRegistryPrototype:JavaScript内建FinalizationRegistry对象的原型,如果FinalizationRegistry类不存在,则为undefined。Float32ArrayPrototype:JavaScript内建Float32Array对象的原型,如果Float32Array类不存在,则为undefined。Float64ArrayPrototype:JavaScript内建Float64Array对象的原型,如果Float64Array类不存在,则为undefined。Int16ArrayPrototype:JavaScript内建Int16Array对象的原型,如果Int16Array类不存在,则为undefined。Int32ArrayPrototype:JavaScript内建Int32Array对象的原型,如果Int32Array类不存在,则为undefined。Int8ArrayPrototype:JavaScript内建Int8Array对象的原型,如果Int8Array类不存在,则为undefined。IntelSegmentIteratorPrototype:JavaScript内建Intl.SegmentIterator对象的原型,如果Intl.SegmentIterator类不存在,则为undefined。InternalErrorPrototype:JavaScript内建InternalError对象的原型,如果InternalError类不存在,则为undefined。IntlCollatorPrototype:JavaScript内建Intl.Collator对象的原型,如果Intl.Collator类不存在,则为undefined。IntlDateTimeFormatPrototype:JavaScript内建Intl.DateTimeFormat对象的原型,如果Intl.DateTimeFormat类不存在,则为undefined。IntlDisplayNamesPrototype:JavaScript内建Intl.DisplayNames对象的原型,如果Intl.DisplayNames类不存在,则为undefined。IntlDurationFormatPrototype:JavaScript内建Intl.DurationFormat对象的原型,如果Intl.DurationFormat类不存在,则为undefined。IntlListFormatPrototype:JavaScript内建Intl.ListFormat对象的原型,如果Intl.ListFormat类不存在,则为undefined。IntlLocalePrototype:JavaScript内建Intl.Locale对象的原型,如果Intl.Locale类不存在,则为undefined。IntlNumberFormatPrototype:JavaScript内建Intl.NumberFormat对象的原型,如果Intl.NumberFormat类不存在,则为undefined。IntlPluralRulesPrototype:JavaScript内建Intl.PluralRules对象的原型,如果Intl.PluralRules类不存在,则为undefined。IntlRelativeTimeFormatPrototype:JavaScript内建Intl.RelativeTimeFormat对象的原型,如果Intl.RelativeTimeFormat类不存在,则为undefined。IntlSegmenterPrototype:JavaScript内建Intl.Segmenter对象的原型,如果Intl.Segmenter类不存在,则为undefined。MapIteratorPrototype:JavaScript内建Map迭代器对象的原型,如果Map迭代器不存在,则为undefined。MapPrototype:JavaScript内建Map对象的原型,如果Map类不存在,则为undefined。PromisePrototype:JavaScript内建Promise对象的原型,如果Promise类不存在,则为undefined。RegExpIteratorPrototype:JavaScript内建RegExp迭代器对象的原型,
类型检测函数
该库提供了以下用于类型检测的函数:
isArguments(value): boolean:判断指定值是否为JavaScript内建的arguments对象。isBoolean(value): boolean:判断指定值是否为JavaScript内建的boolean基本类型或Boolean对象。isBuffer(value): boolean:判断指定值是否为JavaScript内建的ArrayBuffer或SharedArrayBuffer对象。isBuiltInClass(Class): boolean:判断指定的类是否为JavaScript内建类。isCollection(value): boolean:判断指定值是否为JavaScript内建的集合对象,即Map或Set对象。isError(value): boolean:判断指定值是否为JavaScript内建Error类的实例,或Error类子类的实例。isIntl(value): boolean:判断指定值是否为JavaScript内建的Intl命名空间下的对象。isIterator(value): boolean:判断指定值是否为迭代器对象,即具有next()方法的对象。isNumeric(value): boolean:判断指定值是否为JavaScript内建的number基本类型、bigint基本类型或Number对象。isString(value): boolean:判断指定值是否为JavaScript内建的string基本类型或String对象。isTypedArray(value): boolean:判断指定值是否为JavaScript内建的类型化数组对象。isWeak(value): boolean:判断指定值是否为JavaScript内建的弱引用对象,即WeakMap、WeakSet或WeakRef对象。
以下代码展示了如何使用这些函数:
import { isTypedArray } from '@haixing_hu/typeinfo';
function foo(value) {
if (isTypedArray(value)) {
...
} else {
...
}
}为何无法识别Proxy类型
在JavaScript的设计中,Proxy对象的主要目的之一是允许开发者自定义对象操作的行为,它能代理另一个对象(即目标对象)。
Proxy最关键的特性之一便是其透明性——对于外部代码而言,除非代理对象被设计为有意暴露自身,
否则很难区别一个Proxy对象与其所代理的目标对象。这主要是因为Proxy能够拦截并重定义几乎所有的对象基础操作,
包括但不限于属性读取、设置以及属性的枚举。
因此,当使用typeinfo等库尝试获取对象的类型信息时,由于Proxy的这种透明化特征,这些库仅能处理并"看见"最终的操作结果,
而无法直接判断这些操作是否受到Proxy的拦截。如果Proxy完美模仿了其所代理的目标对象的行为,那么就不存在一个可靠的方法,
通过操作结果来断定该对象是否为一个Proxy。简言之,Proxy的设计哲学在于使其自身对外部观察几乎不可见,因此,
除非代理对象特意通过某些拦截行为暴露其身份,否则即便是专门用于获取类型信息的库也无法确切判断一个对象是否为Proxy。
这样的设计极大地增强了Proxy的强大性和灵活性,但同时也意味着直接通过外部检测来识别Proxy对象将是一个挑战。
贡献
如果您发现任何问题或有改进建议,请随时在[GitHub仓库]中提出问题或提交拉取请求。
