4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Array.fromの第1引数のarrayLikeって配列じゃなくてもいいのか

Last updated at Posted at 2021-09-20

オライリーの プログラミングTypeScript P.81に出てきたArray.fromの以下のような使い方を見て、最初意味が分からなかったため、調べてみました。

function fill(length: number, value: string): string[] {
  return Array.from({length}, () => value)
}
fill(3, 'a')
// -> [ 'a', 'a', 'a' ]

Array.from について

Array.fromはMDNによると

Array.from() メソッドは、配列のようなオブジェクトや反復可能オブジェクトから、浅くコピーされた新しい Array インスタンスを生成します。

で、以下のサンプルのような使い方をします。

console.log(Array.from([1, 2, 3], x => x + x));
// expected output: Array [2, 4, 6]

引数の確認をしてみると、第1引数は以下のようになっています。

arrayLike
配列に変換する配列のようなオブジェクトまたは反復可能オブジェクト

今回のケースを改めて見ても、{length}が「配列のようなオブジェクト」にも「反復可能オブジェクト」にも見えなかったため、なぜこれで動くのかが分かりませんでした。

型定義を見てみる

Array.fromの型定義を見てみると、以下のように書かれていました。

./node_modules/typescript/lib/lib.es2015.iterable.d.ts
interface ArrayConstructor {
    /**
     * Creates an array from an iterable object.
     * @param iterable An iterable object to convert to an array.
     */
    from<T>(iterable: Iterable<T> | ArrayLike<T>): T[];

    /**
     * Creates an array from an iterable object.
     * @param iterable An iterable object to convert to an array.
     * @param mapfn A mapping function to call on every element of the array.
     * @param thisArg Value of 'this' used to invoke the mapfn.
     */
    from<T, U>(iterable: Iterable<T> | ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[];
}

Iterableではなさそうなので、ArrayLikeの定義を見てみます。

interface ArrayLike<T> {
    readonly length: number;
    readonly [n: number]: T;
}

すると、上記のような2つのプロパティを持つオブジェクトをArrayLikeと判定しているようでした。
今回の例でいうと、以下のようにどちらの条件も満たしていることになり、{length}ArrayLike<T>にマッチします。

> const length = 3 // 仮で定義
// -> undefined

> {length}.length // `{length}` は `{length: length}`のようにプロパティ名と値の変数名が同じときに省略した記法
// -> 3

> {length}[0]
// -> undefined

もう少し書き方を変えてみると、以下のようなことをやっているイメージです。

> {hoge: 'hoge'}.hoge
// -> 'hoge'

> {0: 'fuga', 1: undefined}[0]
// -> 'fuga'
> {0: 'fuga', 1: undefined}[1]
// -> undefined
> {0: 'fuga', 1: undefined}[2]
// -> undefined

このようなことができるのは、JavaScript、TypeScriptが「対象物は何という名前のものなのか」というよりも、「どう振る舞うのか」、「何ができるのか」という構造を重視しているからです。

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?