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);
}
});
}