1
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?

TypeScript(JavaScript)で配列の開始indexを1始まりに偽装する

Last updated at Posted at 2024-02-25

Proxyオブジェクトを使用して実現します

const org = [1, 3, 5];

const array: any[] = new Proxy(org, {
    get(target, prop) {
      // for...ofループ や スプレッド演算子(...) に対応させる 2025/7/5 追加
      if (prop === Symbol.iterator) {
        return function* () {
          for (let i = 0; i < target.length; i++) {
            yield target[i];
          }
        };
      }

      const index = Number(prop);
      if (!isNaN(index) && index > 0) {
        // プロパティが数値であれば1を引く
        prop = index - 1;
      }
      return Reflect.get(target, prop);
    },
    set(target, prop, value) {
      const index = Number(prop);
      if (!isNaN(index) && index > 0) {
        // プロパティが数値であれば1を引く
        prop = index - 1;
      }
      return Reflect.set(target, prop, value);
    }
});

array[2] = 9;
for (let i = 1; i <= array.length; i++) {
  console.log(i, array[i]); // 1, 9, 5 を順に出力
}

console.log("元の配列は0始まり");
for (let i = 0; i < org.length; i++) {
  console.log(i, org[i]); // 1, 9, 5 を順に出力
}

実行結果

1 1
2 9
3 5
元の配列は0始まり
0 1
1 9
2 5

0ベースの配列を1ベースの配列に変換する関数

多次元配列にも対応

/**
 * 0ベースの配列を1ベースの配列に変換する関数
 * 多次元配列にも対応
 * @param {Array} array - 0ベースの配列
 * @returns {Proxy} 1ベースでアクセス可能な配列のProxyオブジェクト
 */
function createOneBasedArray(array) {
  if (!Array.isArray(array)) {
    throw new Error('引数は配列である必要があります');
  }

  // 配列を再帰的に処理するヘルパー関数
  const processValue = (value) => {
    return Array.isArray(value) ? createOneBasedArray(value) : value;
  };

  return new Proxy(array, {
    get(target, prop) {
      // Symbol.iteratorの処理
      if (prop === Symbol.iterator) {
        return function* () {
          for (let i = 0; i < target.length; i++) {
            yield processValue(target[i]);
          }
        };
      }

      if (typeof prop === 'symbol') {
        return Reflect.get(target, prop);
      }

      // 数値インデックスの処理(1ベース)
      const index = prop;
      if (!isNaN(index) && index > 0) {
        return processValue(target[index - 1]);
      }
      
      // 配列メソッドの処理
      const value = Reflect.get(target, prop);
      if (typeof value === 'function' && Array.isArray(target)) {
        // 配列メソッドは元の配列にバインド
        return value.bind(target);
      }
      
      // 配列の場合は再帰的に処理
      return processValue(value);
    },
    set(target, prop, value) {
      const index = prop;
      if (!isNaN(index) && index > 0) {
        prop = index - 1;
      }
      return Reflect.set(target, prop, value);
    }
  });
}
1
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
1
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?