Skip to content

Instantly share code, notes, and snippets.

@etherealHero
Created June 21, 2024 15:07
Show Gist options
  • Save etherealHero/dea81b8adccf22eaff5aadb6eddbf0b8 to your computer and use it in GitHub Desktop.
Save etherealHero/dea81b8adccf22eaff5aadb6eddbf0b8 to your computer and use it in GitHub Desktop.
if (typeof Object.create !== "function") {
/** Polyfill {@link https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Object/create#polyfill} */
Object.create = (function () {
/** @constructor */
function Temp() {}
return function (proto) {
if (proto === null || (typeof proto !== "object" && typeof proto !== "function")) {
throw TypeError("Object prototype may only be an Object or null: " + proto);
}
Temp.prototype = proto;
var obj = new Temp();
Temp.prototype = null; // Avoid keeping a reference to the prototype
return obj;
};
})();
}
/** @typedef {new (...args: any[]) => any} Constructor */
/**
* Extend Derived from Base.
* @template {Constructor} Derived
* @template {Constructor} Base
* @param {Derived} _derivedCtor - The derived class constructor.
* @param {Base} _baseCtor - The base class constructor.
* @returns {new (...args: ConstructorParameters<Derived>) => Omit<InstanceType<Base>, keyof InstanceType<Derived>> & InstanceType<Derived>}
*/
function extend(_derivedCtor, _baseCtor) {
_derivedCtor.prototype = Object.create(_baseCtor.prototype);
_derivedCtor.prototype.constructor = _derivedCtor;
return /** @type {any} */ (_derivedCtor);
}
///////////////////////
////// POLYFILLS //////
///////////////////////
/** @typedef {InstanceType<Bigben>} IBigben */
var Bigben = (function ($) {
var _class = extend(Bigben, $);
/** @this {InstanceType<$> & Bigben} */
function Bigben() {
$.call(this, {});
this.height = 1000;
}
return _class;
})(Object);
/** @typedef {InstanceType<Person>} IPerson */
var Person = (function ($) {
var _class = extend(Person, $);
/**
* @param {String} name
* @this {InstanceType<$> & Person}
*/
function Person(name) {
$.call(this, {});
this.name = name;
}
/** @type {Function} */
Person.prototype.sayAll = /** @this {IPerson} */ function () {
throw Error("Unimplemented method");
};
/** @param {Pick<IPerson, "name">} toPerson */
Person.prototype.sayHello = /** @this {IPerson} */ function (toPerson) {
alert("Hello " + toPerson.name + " from " + this.name);
};
return _class;
})(Object);
/** @typedef {InstanceType<Admin>} IAdmin */
var Admin = (function ($) {
var _class = extend(Admin, $);
/**
* @param {String} name
* @param {Number} accessLevel
* @this {InstanceType<$> & Admin}
*/
function Admin(name, accessLevel) {
$.call(this, name);
this.accessLevel = accessLevel;
}
/**
* @param {Number} count
*/
Admin.prototype.sayAll = /** @this {IAdmin} */ function (count) {
var stack = [];
for (var i = 0; i < count; i++) {
stack.push("Admin " + this.name + " say all: Hello!");
}
alert(stack.join(", "));
};
return _class;
})(Person);
/** @typedef {InstanceType<SuperAdmin>} ISuperAdmin */
var SuperAdmin = (function ($) {
var _class = extend(SuperAdmin, $);
/**
* @param {String} name
* @param {Number} accessLevel
* @this {InstanceType<$> & SuperAdmin}
*/
function SuperAdmin(name, accessLevel) {
$.call(this, name, accessLevel);
this.superAdminLevel = 100;
}
SuperAdmin.prototype.sayHello = /** @this {ISuperAdmin} */ function () {
alert("qq");
return "qq";
};
/**
* Отправить всем сообщение
* @param {String} message
* @param {String} postfix
*/
SuperAdmin.prototype.sayAll = /** @this {ISuperAdmin} */ function (message, postfix) {
var msg = "Message " + message + " from " + this.name + postfix;
alert(msg);
return msg;
};
return _class;
})(Admin);
/** @typedef {InstanceType<WorkerPerson>} IWorkerPerson */
var WorkerPerson = (function ($) {
var _class = extend(WorkerPerson, $);
/**
* @param {String} name
* @constructor @typedef {InstanceType<$> & WorkerPerson} _ @this _
*/
function WorkerPerson(name) {
$.call(this, name);
}
return _class;
})(Person);
var myPerson = new Person("Alex");
var myAdmin = new Admin("Maxim", 1);
var myWorkerPerson = new WorkerPerson("Andrew");
var mySuperAdmin = new SuperAdmin("Kek", 2);
var myBigben = new Bigben();
mySuperAdmin.name;
mySuperAdmin.sayHello();
mySuperAdmin.sayHello();
myAdmin.sayAll(2);
mySuperAdmin.sayAll("message", "LALALA");
myAdmin.sayHello(mySuperAdmin);
nameOfPerson(mySuperAdmin);
nameOfSA(mySuperAdmin);
/**
* @param {Pick<IPerson, "name">} person
* @returns {String}
*/
function nameOfPerson(person) {
return person.name;
}
/**
* @param {ISuperAdmin} SA
* @returns {String}
*/
function nameOfSA(SA) {
return SA.name;
}
/**
* @param {Person} personConstructor
* @param {String} name
* @returns {IPerson}
*/
function createPerson(personConstructor, name) {
var newPerson = new personConstructor(name);
return newPerson;
}
createPerson(Person, "name");
alert(
[
"// все должны быть от Object",
(myBigben instanceof Object ? "PASSED " : "FAIL ") + " myBigben instanceof Object",
(myPerson instanceof Object ? "PASSED " : "FAIL ") + " myPerson instanceof Object",
(myAdmin instanceof Object ? "PASSED " : "FAIL ") + " myAdmin instanceof Object",
(myWorkerPerson instanceof Object ? "PASSED " : "FAIL ") + " myWorkerPerson instanceof Object",
(mySuperAdmin instanceof Object ? "PASSED " : "FAIL ") + " mySuperAdmin instanceof Object",
"",
"// всё от Person",
(!({} instanceof Bigben) ? "PASSED " : "FAIL ") + "!({} instanceof Bigben)",
(!({} instanceof Person) ? "PASSED " : "FAIL ") + "!({} instanceof Person)",
(!(myBigben instanceof Person) ? "PASSED " : "FAIL ") + "!(myBigben instanceof Person)",
(myPerson instanceof Person ? "PASSED " : "FAIL ") + " myPerson instanceof Person ",
(myAdmin instanceof Person ? "PASSED " : "FAIL ") + " myAdmin instanceof Person ",
(myWorkerPerson instanceof Person ? "PASSED " : "FAIL ") + " myWorkerPerson instanceof Person ",
(mySuperAdmin instanceof Person ? "PASSED " : "FAIL ") + " mySuperAdmin instanceof Person ",
"",
"// админы админы",
(!({} instanceof Admin) ? "PASSED " : "FAIL ") + "!({} instanceof Admin)",
(!(myBigben instanceof Admin) ? "PASSED " : "FAIL ") + "!(myBigben instanceof Admin)",
(!(myPerson instanceof Admin) ? "PASSED " : "FAIL ") + "!(myPerson instanceof Admin)",
(!(myWorkerPerson instanceof Admin) ? "PASSED " : "FAIL ") + "!(myWorkerPerson instanceof Admin)",
(myAdmin instanceof Admin ? "PASSED " : "FAIL ") + " myAdmin instanceof Admin ",
(mySuperAdmin instanceof Admin ? "PASSED " : "FAIL ") + " mySuperAdmin instanceof Admin ",
"",
"// СА только СА",
(!({} instanceof SuperAdmin) ? "PASSED " : "FAIL ") + "!({} instanceof SuperAdmin)",
(!(myPerson instanceof SuperAdmin) ? "PASSED " : "FAIL ") + "!(myPerson instanceof SuperAdmin)",
(!(myBigben instanceof SuperAdmin) ? "PASSED " : "FAIL ") + "!(myBigben instanceof SuperAdmin)",
(!(myAdmin instanceof SuperAdmin) ? "PASSED " : "FAIL ") + "!(myAdmin instanceof SuperAdmin)",
(!(myWorkerPerson instanceof SuperAdmin) ? "PASSED " : "FAIL ") + "!(myWorkerPerson instanceof SuperAdmin)",
(mySuperAdmin instanceof SuperAdmin ? "PASSED " : "FAIL ") + " mySuperAdmin instanceof SuperAdmin ",
"",
"// верный констуктор",
// @ts-ignore
(Var.ClassOf(myBigben) === "Bigben" ? "PASSED " : "FAIL ") + " Var.ClassOf(myBigben) === 'Bigben'",
// @ts-ignore
(Fnp.TypeOf(myBigben) === "Bigben" ? "PASSED " : "FAIL ") + " Fnp.TypeOf (myBigben) === 'Bigben'",
// @ts-ignore
(Var.ClassOf(myPerson) === "Person" ? "PASSED " : "FAIL ") + " Var.ClassOf(myPerson) === 'Person'",
// @ts-ignore
(Fnp.TypeOf(myPerson) === "Person" ? "PASSED " : "FAIL ") + " Fnp.TypeOf (myPerson) === 'Person'",
// @ts-ignore
(Var.ClassOf(myWorkerPerson) === "WorkerPerson" ? "PASSED " : "FAIL ") + " Var.ClassOf(myWorkerPerson) === 'WorkerPerson'",
// @ts-ignore
(Fnp.TypeOf(myWorkerPerson) === "WorkerPerson" ? "PASSED " : "FAIL ") + " Fnp.TypeOf (myWorkerPerson) === 'WorkerPerson'",
// @ts-ignore
(Var.ClassOf(myAdmin) === "Admin" ? "PASSED " : "FAIL ") + " Var.ClassOf(myAdmin) === 'Admin' ",
// @ts-ignore
(Fnp.TypeOf(myAdmin) === "Admin" ? "PASSED " : "FAIL ") + " Fnp.TypeOf (myAdmin) === 'Admin' ",
// @ts-ignore
(Var.ClassOf(mySuperAdmin) === "SuperAdmin" ? "PASSED " : "FAIL ") + " Var.ClassOf(mySuperAdmin) === 'SuperAdmin'",
// @ts-ignore
(Fnp.TypeOf(mySuperAdmin) === "SuperAdmin" ? "PASSED " : "FAIL ") + " Fnp.TypeOf (mySuperAdmin) === 'SuperAdmin'",
""
].join("\r\n")
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment