Skip to content

Instantly share code, notes, and snippets.

@ythosa
Created December 4, 2020 23:12
Show Gist options
  • Save ythosa/3e3d19f1a54666d2d46d13f51ab2f153 to your computer and use it in GitHub Desktop.
Save ythosa/3e3d19f1a54666d2d46d13f51ab2f153 to your computer and use it in GitHub Desktop.
all-syntax-typescript.ts
// //
// --- Generics --- //
// //
const cars: Array<number|string> = [1, "aa"]
function mergeObjects<T1 extends object, T2 extends object>
(a: T1, b: T2): T1 & T2 {
return Object.assign({}, a, b)
}
const merged = mergeObjects({ a: 1}, { b: 2 }) // merged.a; merged.b
interface Length { length: number }
function kek<T extends Length>(meh: T) { return meh.length }
function getObjectValue<T extends object, R extends keyof T>
(obj: T, key: R): T[R] { // Object keys types
return obj[key]
}
class Collection<T extends number|string|boolean> { // Class Generics
constructor(private data: Array<T> = []) {}
add(item: T) { this.data.push(item) }
remove(item: T) { this.data.filter(el => el != item) }
get items(): Array<T> { return this.data }
}
const myCollection = new Collection<string>(['Type', 'Script']);
console.log(myCollection.items);
interface Car { model: string; year: string } // Partial
function createCar(model: string, year: string): Car {
const car: Partial<Car> = {}
car.model = model; car.year = year;
return car as Car;
}
const myCars: Readonly<Array<string>> = ['pi', 'pi']; // Readonly variable
// //
// --- Decorators --- //
// //
function Log(constructor: Function) {
console.log('Log: ', constructor)
}
function LogProperty(target: any, propName: string | Symbol) {
console.log('LogProperty: ', target, propName)
}
function LogMethod(target: any, propName: string | Symbol,
descriptor: PropertyDescriptor
) {
console.log('LogMethod: ', target, propName, descriptor)
}
@Log // -> Function [ ComponentTest ]
class ComponentTest {
@LogProperty
name: string; // -> ComponentTest {} _ name
constructor(name: string) {
this.name = name;
}
@LogMethod // -> ComponentTest {} logName {value: [Function: logName], writable: true...
logName(): void {
console.log(`Component Name: ${this.name}`)
}
@LogMethod // -> the same but with .get in propertyDescriptor
get componentName() { return this.name }
}
////
interface ComponentDecorator {
selector: string;
template: string;
}
function Component(config: ComponentDecorator) {
return function
<T extends { new(...args: any[]): object }>
(Constructor: T) {
return class extends Constructor {
constructor(...args: any[]) {
super(...args)
const el = document.querySelector(config.selector)!
el.innerHTML = config.template
}
}
}
}
function Bind(_: any, _2: any, descriptor: PropertyDescriptor): PropertyDescriptor {
const original = descriptor.value;
return {
configurable: true,
enumerable: false,
get() {
return original.bind(this)
}
}
}
@Component({
selector: '#card',
template: `<div class='card>Card Component</div`
})
class CardComponent {
constructor(private name: string) {}
@Bind
logName(): void {
console.log(`Component Name: ${this.name}`)
}
}
////
type ValidatorType = 'required' | 'email';
interface ValidatorConfig {
[prop: string]: {
[validateProp: string]: ValidatorType
}
}
const validators: ValidatorConfig = {};
function Required(target: any, propName: string | Symbol) {
validators[target.constructor.name] = {
...validators[target.constructor.name],
propName: 'required'
}
}
function validate(obj: any): boolean {
const objConfig = validators[obj.constructor.name]
if (!objConfig) return true
let isValid = true;
Object.keys(objConfig).forEach(key => {
if (objConfig[key] === 'required') {
isValid = isValid && !!obj[key]
}
})
return isValid
}
class Form {
@Required
public email: string | void;
constructor(email?: string) {
this.email = email;
}
}
const form = new Form();
if (validate(form)) {
console.log(`Valid Form: ${form}`);
} else {
console.log('Form Validation Error')
}
// //
// --- Namespaces --- //
// //
/// <reference path='form-namespace.ts' /> - to import namespaces
namespace FormNamespace {
type Type = 'inline' | 'block'
type Id = number | string
export class MyForm {
private type: Type = 'inline'
private id: Id = 1
getinfo() {
return {
id: this.id,
type: this.type,
}
}
}
}
const fm = new FormNamespace.MyForm();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment