Last active
September 8, 2025 15:03
-
-
Save n1215/b4eb3954a31201dff35afbd9c9565061 to your computer and use it in GitHub Desktop.
TypeScript and abstract data type implementations. combinations of object creation methods and oop/functional styles.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// oop style (class based) / class instantiation | |
class LocalTime { | |
constructor( | |
private readonly _hour: number, | |
private readonly _minutes: number, | |
private readonly _seconds: number | |
) { | |
if (_hour < 0 || _hour > 23 || !Number.isInteger(_hour)) { | |
throw new Error("hour must be an integer between 0 and 23"); | |
} | |
if (_minutes < 0 || _minutes > 59 || !Number.isInteger(_minutes)) { | |
throw new Error("minutes must be an integer between 0 and 59"); | |
} | |
if (_seconds < 0 || _seconds > 59 || !Number.isInteger(_seconds)) { | |
throw new Error("seconds must be an integer between 0 and 59"); | |
} | |
} | |
get hour(): number { | |
return this._hour; | |
} | |
get minutes(): number { | |
return this._minutes; | |
} | |
get seconds(): number { | |
return this._seconds; | |
} | |
isAfter(another: LocalTime): boolean { | |
if (this.hour > another.hour) { | |
return true; | |
} | |
if (this.hour < another.hour) { | |
return false; | |
} | |
if (this.minutes > another.minutes) { | |
return true; | |
} | |
return this.seconds > another.seconds; | |
} | |
} | |
const localTime = new LocalTime(10, 0, 1); | |
const localTime2 = new LocalTime(10, 0, 0); | |
console.log(localTime.hour, localTime.minutes, localTime.seconds); | |
console.log(localTime.isAfter(localTime2)); | |
// compile time type error | |
const invalidLocalTime: LocalTime = { | |
hour: 25, | |
minutes: 0, | |
seconds: 0, | |
isAfter(another: LocalTime): boolean { | |
return true; | |
} | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// oop style (prototype based) / constructor function | |
type LocalTime = { | |
readonly hour: number; | |
readonly minutes: number; | |
readonly seconds: number; | |
isAfter(other: LocalTime): boolean; | |
} | |
/** | |
* @constructor | |
* @returns {LocalTime} | |
*/ | |
function LocalTime(hour: number, minutes: number, seconds: number) { | |
if (hour < 0 || hour > 23 || !Number.isInteger(hour)) { | |
throw new Error("hour must be an integer between 0 and 23"); | |
} | |
if (minutes < 0 || minutes > 59 || !Number.isInteger(minutes)) { | |
throw new Error("minutes must be an integer between 0 and 59"); | |
} | |
if (seconds < 0 || seconds > 59 || !Number.isInteger(seconds)) { | |
throw new Error("seconds must be an integer between 0 and 59"); | |
} | |
this.hour = hour; | |
this.minutes = minutes; | |
this.seconds = seconds; | |
} | |
LocalTime.prototype.isAfter = function(another: LocalTime): boolean { | |
if (this.hour > another.hour) { | |
return true; | |
} | |
if (this.hour < another.hour) { | |
return false; | |
} | |
if (this.minutes > another.minutes) { | |
return true; | |
} | |
return this.seconds > another.seconds; | |
}; | |
const localTime = new LocalTime(10, 0, 1); | |
const localTime2 = new LocalTime(10, 0, 0); | |
console.log(localTime.hour, localTime.minutes, localTime.seconds); | |
console.log(localTime.isAfter(localTime2)); | |
// no type error | |
const invalidLocalTime: LocalTime = { | |
hour: 25, | |
minutes: 0, | |
seconds: 0, | |
isAfter(another: LocalTime): boolean { | |
return true; | |
} | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// oop style / factory function | |
type LocalTime = { | |
readonly hour: number; | |
readonly minutes: number; | |
readonly seconds: number; | |
isAfter(other: LocalTime): boolean; | |
}; | |
function createLocalTime( | |
hour: number, | |
minutes: number, | |
seconds: number | |
): LocalTime { | |
if (hour < 0 || hour > 23 || !Number.isInteger(hour)) { | |
throw new Error("hour must be a integer between 0 and 23"); | |
} | |
if (minutes < 0 || minutes > 59 || !Number.isInteger(minutes)) { | |
throw new Error("minutes must be a integer between 0 and 59"); | |
} | |
if (seconds < 0 || seconds > 59 || !Number.isInteger(seconds)) { | |
throw new Error("seconds must be a integer between 0 and 59"); | |
} | |
const self = { | |
hour, | |
minutes, | |
seconds, | |
isAfter(another: LocalTime): boolean { | |
if (self.hour > another.hour) { | |
return true; | |
} | |
if (self.hour < another.hour) { | |
return false; | |
} | |
if (self.minutes > another.minutes) { | |
return true; | |
} | |
return self.seconds > another.seconds; | |
} | |
}; | |
return self; | |
} | |
const localTime = createLocalTime(10, 0, 1); | |
const localTime2 = createLocalTime(10, 0, 0); | |
console.log(localTime.hour, localTime.minutes, localTime.seconds); | |
console.log(localTime.isAfter(localTime2)); | |
// no type error | |
const invalidLocalTime: LocalTime = { | |
hour: 25, | |
minutes: 0, | |
seconds: 0, | |
isAfter(another: LocalTime): boolean { | |
return true; | |
} | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// oop style / factory method by companion object | |
type LocalTime = { | |
readonly hour: number; | |
readonly minutes: number; | |
readonly seconds: number; | |
isAfter(other: LocalTime): boolean; | |
}; | |
const LocalTime = { | |
of(hour: number, minutes: number, seconds: number): LocalTime { | |
if (hour < 0 || hour > 23 || !Number.isInteger(hour)) { | |
throw new Error("hour must be a integer between 0 and 23"); | |
} | |
if (minutes < 0 || minutes > 59 || !Number.isInteger(minutes)) { | |
throw new Error("minutes must be a integer between 0 and 59"); | |
} | |
if (seconds < 0 || seconds > 59 || !Number.isInteger(seconds)) { | |
throw new Error("seconds must be a integer between 0 and 59"); | |
} | |
const self: LocalTime = { | |
hour, | |
minutes, | |
seconds, | |
isAfter(another: LocalTime): boolean { | |
if (self.hour > another.hour) { | |
return true; | |
} | |
if (self.hour < another.hour) { | |
return false; | |
} | |
if (self.minutes > another.minutes) { | |
return true; | |
} | |
return self.seconds > another.seconds; | |
} | |
}; | |
return self; | |
} | |
}; | |
const localTime = LocalTime.of(10, 0, 1); | |
const localTime2 = LocalTime.of(10, 0, 0); | |
console.log(localTime.hour, localTime.minutes, localTime.seconds); | |
console.log(localTime.isAfter(localTime2)); | |
// no type error | |
const invalidLocalTime: LocalTime = { | |
hour: 25, | |
minutes: 0, | |
seconds: 0, | |
isAfter(another: LocalTime): boolean { | |
return true; | |
} | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// fp style(type has no method) | |
type LocalTime = { | |
readonly hour: number; | |
readonly minutes: number; | |
readonly seconds: number; | |
}; | |
function createLocalTime( | |
hour: number, | |
minutes: number, | |
seconds: number | |
): LocalTime { | |
if (hour < 0 || hour > 23 || !Number.isInteger(hour)) { | |
throw new Error("hour must be an integer between 0 and 23"); | |
} | |
if (minutes < 0 || minutes > 59 || !Number.isInteger(minutes)) { | |
throw new Error("minutes must be an integer between 0 and 59"); | |
} | |
if (seconds < 0 || seconds > 59 || !Number.isInteger(seconds)) { | |
throw new Error("seconds must be an integer between 0 and 59"); | |
} | |
return { | |
hour, | |
minutes, | |
seconds | |
}; | |
} | |
function isAfter(one: LocalTime, another: LocalTime) { | |
if (one.hour > another.hour) { | |
return true; | |
} | |
if (one.hour < another.hour) { | |
return false; | |
} | |
if (one.minutes > another.minutes) { | |
return true; | |
} | |
return one.seconds > another.seconds; | |
} | |
const localTime = createLocalTime(10, 0, 1); | |
const localTime2 = createLocalTime(10, 0, 0); | |
console.log(localTime.hour, localTime.minutes, localTime.seconds); | |
console.log(isAfter(localTime, localTime2)); | |
// no type error | |
const invalidLocalTime: LocalTime = { | |
hour: 25, | |
minutes: 0, | |
seconds: 0, | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// fp style + strictly typed | |
type Hour = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23; | |
type Minutes = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | |
| 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | |
| 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | |
| 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59; | |
type Seconds = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | |
| 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | |
| 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | |
| 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59; | |
type LocalTime = { | |
readonly hour: Hour; | |
readonly minutes: Minutes; | |
readonly seconds: Seconds; | |
}; | |
function createLocalTime( | |
hour: Hour, | |
minutes: Minutes, | |
seconds: Seconds | |
): LocalTime { | |
return { | |
hour, | |
minutes, | |
seconds | |
}; | |
} | |
function isAfter(one: LocalTime, another: LocalTime) { | |
if (one.hour > another.hour) { | |
return true; | |
} | |
if (one.hour < another.hour) { | |
return false; | |
} | |
if (one.minutes > another.minutes) { | |
return true; | |
} | |
return one.seconds > another.seconds; | |
} | |
const localTime = createLocalTime(10, 0, 1); | |
const localTime2 = createLocalTime(10, 0, 0); | |
console.log(localTime.hour, localTime.minutes, localTime.seconds); | |
console.log(isAfter(localTime, localTime2)); | |
const invalidLocalTime: LocalTime = { | |
hour: 25, // compile time type error | |
minutes: 0, | |
seconds: 0, | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// fp style + branded type | |
export const BrandTypeId: unique symbol = Symbol.for("mylib/Brand") | |
export interface Brand<in out K extends string | symbol> { | |
readonly [BrandTypeId]: { | |
readonly [k in K]: K | |
} | |
} | |
type LocalTime = { | |
readonly hour: number; | |
readonly minutes: number; | |
readonly seconds: number; | |
} & Brand<"LocalTime">; | |
function createLocalTime( | |
hour: number, | |
minutes: number, | |
seconds: number | |
): LocalTime { | |
if (hour < 0 || hour > 23 || !Number.isInteger(hour)) { | |
throw new Error("hour must be an integer between 0 and 23"); | |
} | |
if (minutes < 0 || minutes > 59 || !Number.isInteger(minutes)) { | |
throw new Error("minutes must be an integer between 0 and 59"); | |
} | |
if (seconds < 0 || seconds > 59 || !Number.isInteger(seconds)) { | |
throw new Error("seconds must be an integer between 0 and 59"); | |
} | |
return { | |
hour, | |
minutes, | |
seconds | |
} as LocalTime; | |
} | |
function isAfter(one: LocalTime, another: LocalTime) { | |
if (one.hour > another.hour) { | |
return true; | |
} | |
if (one.hour < another.hour) { | |
return false; | |
} | |
if (one.minutes > another.minutes) { | |
return true; | |
} | |
return one.seconds > another.seconds; | |
} | |
const localTime = createLocalTime(10, 0, 1); | |
const localTime2 = createLocalTime(10, 0, 0); | |
console.log(localTime.hour, localTime.minutes, localTime.seconds); | |
console.log(isAfter(localTime, localTime2)); | |
// compile time type error | |
const invalidLocalTime: LocalTime = { | |
hour: 25, | |
minutes: 0, | |
seconds: 0, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment