Created
December 4, 2020 23:12
-
-
Save ythosa/3e3d19f1a54666d2d46d13f51ab2f153 to your computer and use it in GitHub Desktop.
all-syntax-typescript.ts
This file contains 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
// // | |
// --- 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