Вы не хотите использовать наследование, потому что вы не намерены разрешить использование CustomArray<T>
одинаково, как Array<T>
.
Что вы можете сделать, это определить свой новый тип как функцию Array<T>
и сделать конструктор CustomArray
таким же, как конструктор Array
во время выполнения:
type CustomArray<T> = Pick<Array<T>, Exclude<keyof Array<T>, "shift" | "pop">>;
const CustomArray: new <T>() => CustomArray<T> = Array;
let c1 = new CustomArray<number>();
c1.push(10, 20, 30, 40, 50); // okay
c1.shift(); // error
c1.pop(); // error
c1.sort(); // okay
Тоработает так, как вы просили.Но имейте в виду, что это «поверхностное» преобразование Array<T>
.Например, метод sort()
будет по-прежнему возвращать Array<T>
, а не CustomArray<T>
:
c1.sort().pop(); // okay
Если вы действительно хотите «глубокое» преобразование, при котором все соответствующие упоминания Array<T>
заменяются на CustomArray<T>
, вам, возможно, придется пойти дальше и вручную указать полный интерфейс, так как автоматическое сопоставление вряд ли будет работать так, как вы хотите:
interface CustomArray<T> {
length: number;
toString(): string;
toLocaleString(): string;
// pop(): T | undefined;
push(...items: T[]): number;
concat(...items: ConcatArray<T>[]): CustomArray<T>;
concat(...items: (T | ConcatArray<T>)[]): CustomArray<T>;
join(separator?: string): string;
reverse(): CustomArray<T>;
// shift(): T | undefined;
slice(start?: number, end?: number): CustomArray<T>;
sort(compareFn?: (a: T, b: T) => number): this;
// ... ALL the other methods, omitted for brevity
}
const CustomArray: new <T>() => CustomArray<T> = Array;
const c1 = new CustomArray();
c1.push(10, 20, 30, 40, 50); // okay
c1.shift(); // error
c1.pop(); // error
c1.sort(); // okay
c1.sort().pop(); // error
Это более утомительно, но вы можете осуществлять намного больший контрольза результат.Любой способ должен работать для вас, хотя.Надеюсь, это поможет;удачи!