【若川视野 x 源码共读】第33期| arrify 转数组

141 阅读1分钟

本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。

源码地址

github.com/sindresorhu…

源码解析

这次的源码几乎没有所谓难度,全然是对于传入参数的类型作判断,而后返回相应数组。

export default function arrify(value) {
	if (value === null || value === undefined) {
		return [];
	}

	if (Array.isArray(value)) {
		return value;
	}

	if (typeof value === 'string') {
		return [value];
	}

	if (typeof value[Symbol.iterator] === 'function') {
		return [...value];
	}

	return [value];
}

其中最为主要的是最后一个if处理对于具备iterator可迭代的value作数组转化,在ES6相关实现中,使用「...」就可以将其转化为数组。

这个库如此简单,在此结束好像有种啥都没讲的感觉。而TS相关的文件也很简单,其声明文件:

export default function arrify<ValueType>(
	value: ValueType
): ValueType extends (null | undefined)
	? [] // eslint-disable-line  @typescript-eslint/ban-types
	: ValueType extends string
		? [string]
		: ValueType extends readonly unknown[]
			? ValueType
			: ValueType extends Iterable<infer T>
				? T[]
				: [ValueType];

声明文件中对ValueType及参数的类型作了检验。整个arrify为一个泛型声明,根据valueType的判断返回一个数组。结构上与index.js实现的判断一致。

这里我稍微不理解的是(TS小白),对于unknown数组类型,前面为何要加readonly来约束只读,在测试文件声明中有这么一条,所以是约束arrify传递的数组不允许更改?

expectError(arrify(['🦄'] as const).push(''));