diff --git a/README.md b/README.md new file mode 100644 index 0000000..c02305d --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# typescript-training + +## To watch run this in repository root +`npx mocha -r ts-node/register --watch --watch-extensions ts '**/*spec.ts'` diff --git a/src/01_variables/variables_0/variables0.spec.ts b/src/01_variables/variables_0/variables0.spec.ts index ecb6eb3..7cd0135 100644 --- a/src/01_variables/variables_0/variables0.spec.ts +++ b/src/01_variables/variables_0/variables0.spec.ts @@ -2,15 +2,15 @@ import { expect } from 'chai'; describe('Variables declaration and assignment', () => { - // it('nums has number type and proper value', () => { - // var numWithValue = 1; - // var numWithoutValue: number; + it('nums has number type and proper value', () => { + var numWithValue = 1; + var numWithoutValue: number; - // expect(typeof numWithValue).to.equal(/*exercise*/); - // expect(numWithValue).to.equal(/*exercise*/); + expect(typeof numWithValue).to.equal("number"); + expect(numWithValue).to.equal(1); - // expect(typeof numWithoutValue).to.equal(/*exercise*/); - // expect(numWithoutValue).to.equal(/*exercise*/); - // }); + expect(typeof numWithoutValue).to.equal("undefined"); + expect(numWithoutValue).to.equal(undefined); + }); }); diff --git a/src/01_variables/variables_2/variables2.spec.ts b/src/01_variables/variables_2/variables2.spec.ts index 55dae7c..5812e9d 100644 --- a/src/01_variables/variables_2/variables2.spec.ts +++ b/src/01_variables/variables_2/variables2.spec.ts @@ -55,32 +55,32 @@ describe('Variables basic types', () => { // expect(Color.Blue).to.equal(/*exercise*/); // }) - // it('Tuple', () => { - // let x: [string, number]; - // x = ["hello", 10]; - - // expect(typeof x).to.equal(/*exercise*/); - // expect(typeof x[0]).to.equal(/*exercise*/); - // expect(typeof x[1]).to.equal(/*exercise*/); - // }) - - // it('Array of tuples', () => { - // let x: [string, number][]; - // x = [["hello", 10], ['bye', 2]]; - - // expect(typeof x).to.equal(/*exercise*/); - // expect(typeof x[0]).to.equal(/*exercise*/); - // expect(typeof x[1]).to.equal(/*exercise*/); - // expect(typeof x[0][0]).to.equal(/*exercise*/); - // expect(typeof x[0][1]).to.equal(/*exercise*/); - // }) - - // it('Never', () => { - // function fail(): never { - // /*exercise*/ - // } - - // expect(typeof fail).to.equal("function"); - // }) + it('Tuple', () => { + let x: [string, number]; + x = ["hello", 10]; + + expect(typeof x).to.equal("object"); + expect(typeof x[0]).to.equal("string"); + expect(typeof x[1]).to.equal("number"); + }) + + it('Array of tuples', () => { + let x: [string, number][]; + x = [["hello", 10], ['bye', 2]]; + + expect(typeof x).to.equal("object"); + expect(typeof x[0]).to.equal("object"); + expect(typeof x[1]).to.equal("object"); + expect(typeof x[0][0]).to.equal("string"); + expect(typeof x[0][1]).to.equal("number"); + }) + + it('Never', () => { + function fail(): never { + while(true) {} + } + + expect(typeof fail).to.equal("function"); + }) }); \ No newline at end of file diff --git a/src/01_variables/variables_4/variables4.spec.ts b/src/01_variables/variables_4/variables4.spec.ts index dab06cb..4a8c34e 100644 --- a/src/01_variables/variables_4/variables4.spec.ts +++ b/src/01_variables/variables_4/variables4.spec.ts @@ -2,55 +2,55 @@ import { expect } from 'chai'; describe('destructuring, spread', () => { - // it('spread for array', () => { - // let first = [1, 2]; - // let second = [3, 4]; - // let bothPlus = [0, ...first, ...second, 5]; + it('spread for array', () => { + let first = [1, 2]; + let second = [3, 4]; + let bothPlus = [0, ...first, ...second, 5]; - // expect(bothPlus.length).to.equal(/*exercise*/); - // expect(bothPlus[2]).to.equal(/*exercise*/); - // }); + expect(bothPlus.length).to.equal(6); + expect(bothPlus[2]).to.equal(2); + }); - // it('spread for object', () => { - // let defaults = { food: "spicy", price: "$$", ambiance: "noisy" }; - // let search = { food: "rich", ...defaults }; + it('spread for object', () => { + let defaults = { food: "spicy", price: "$$", ambiance: "noisy" }; + let search = { food: "rich", ...defaults }; - // expect(search.price).to.equal(/*exercise*/); - // expect(search.food).to.equal(/*exercise*/); - // }); + expect(search.price).to.equal("$$"); + expect(search.food).to.equal("spicy"); + }); - // it('destructuring', () => { - // let input = [1, 2]; - // let [first, second] = input; + it('destructuring', () => { + let input = [1, 2]; + let [first, second] = input; - // expect(first).to.equal(/*exercise*/); - // expect(second).to.equal(/*exercise*/); - // }); + expect(first).to.equal(1); + expect(second).to.equal(2); + }); - // it('destructuring with params', () => { - // let [first, ...rest] = [1, 2, 3, 4]; + it('destructuring with params', () => { + let [first, ...rest] = [1, 2, 3, 4]; - // expect(first).to.equal(/*exercise*/); - // expect(rest).to.deep.equal(/*exercise*/); - // }); + expect(first).to.equal(1); + expect(rest).to.deep.equal([2,3,4]); + }); - // it('destructuring and spreading', () => { - // let first = [1, 2]; - // let second = [3, 4]; - // let bothPlus = [0, ...first, ...second]; - // let [firstElement, ...rest] = [...bothPlus]; + it('destructuring and spreading', () => { + let first = [1, 2]; + let second = [3, 4]; + let bothPlus = [0, ...first, ...second]; + let [firstElement, ...rest] = [...bothPlus]; - // expect(firstElement).to.equal(/*exercise*/); - // expect([...rest]).to.deep.equal(/*exercise*/); - // }); + expect(firstElement).to.equal(0); + expect([...rest]).to.deep.equal([1,2,3,4]); + }); - // it('restrict parameters for function by custom type', () => { - // type C = { a: string, b?: number } - // function f({ a, b }: C): any { - // return a + b; - // } + it('restrict parameters for function by custom type', () => { + type C = { a: string, b?: number } + function f({ a, b }: C): any { + return a + b; + } - // expect(f({a: 'test', b: 2})).to.equal(/*exercise*/); - // }); + expect(f({a: 'test', b: 2})).to.equal("test2"); + }); }); \ No newline at end of file diff --git a/src/02_functions/functions_2_this_arrow/functions2.spec.ts b/src/02_functions/functions_2_this_arrow/functions2.spec.ts index 55e40d8..b1b487c 100644 --- a/src/02_functions/functions_2_this_arrow/functions2.spec.ts +++ b/src/02_functions/functions_2_this_arrow/functions2.spec.ts @@ -14,18 +14,19 @@ describe('Functions - this and arrows functions', () => { // expect(myObject.getValue()).to.equal('test'); // }); - // it('This different scope behavior', () => { + it('This different scope behavior', () => { - // // exercise - fix error in myObject - // let myObject = { - // value: "test", - // getValue: function() { - // return function() { - // return this.value; - // } - // } - // } + // // exercise - fix error in myObject + // let myObject = { + // value: "test", + // getValue: function() { + // return function() { + // return this.value; + // } + // } + // } + + // expect(myObject.getValue()()).to.equal('test'); + }); +}); - // expect(myObject.getValue()()).to.equal('test'); - // }); -}); \ No newline at end of file diff --git a/src/03_classes/classes_1/classes1.spec.ts b/src/03_classes/classes_1/classes1.spec.ts index 1412929..ae78152 100644 --- a/src/03_classes/classes_1/classes1.spec.ts +++ b/src/03_classes/classes_1/classes1.spec.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; class Greeter { - greeting: string; // default it is public, not like in C# or Java + private greeting: string; // default it is public, not like in C# or Java constructor(message: string) { // multiple constructor implementations are not allowed this.greeting = message; } @@ -42,11 +42,11 @@ describe('Class - constructor and function', () => { // expect(greeter2.greet()).to.equal(/*Exercise*/); // }); - // it('Private properties hacking', () => { - // var greeter = new NewGreeter('Test'); + it('Private properties hacking', () => { + var greeter = new NewGreeter('Test'); - // expect(/*Exercise*/).to.equal('Test'); - // expect(/*Exercise*/).to.equal('Secret Greet'); - // }); + expect(greeter['greeting']).to.equal('Test'); + expect(eval('greeter.secretGreet')()).to.equal('Secret Greet'); + }); }); \ No newline at end of file diff --git a/src/03_classes/classes_2/classes2.spec.ts b/src/03_classes/classes_2/classes2.spec.ts index 02feb0b..0f0489e 100644 --- a/src/03_classes/classes_2/classes2.spec.ts +++ b/src/03_classes/classes_2/classes2.spec.ts @@ -57,13 +57,13 @@ describe('Class - inheritance', () => { // expect(cat.getLives()).to.equal(/*Exercise*/); // }); - // it('Cat - Animal inheritance - accessors', () => { - // var cat = new Cat(); - // cat.catDistance = 100; - // cat.catDistance = 100; - // cat.move(100); - - // expect(cat.catDistance).to.equal(/*Exercise*/); - // }); + it('Cat - Animal inheritance - accessors', () => { + var cat = new Cat(); + cat.catDistance = 100; + cat.catDistance = 100; + cat.move(100); + + expect(cat.catDistance).to.equal(300); + }); }); diff --git a/src/03_classes/classes_3/classes3.spec.ts b/src/03_classes/classes_3/classes3.spec.ts index 317e509..f03b9dd 100644 --- a/src/03_classes/classes_3/classes3.spec.ts +++ b/src/03_classes/classes_3/classes3.spec.ts @@ -3,6 +3,7 @@ import { expect } from 'chai'; abstract class Department { constructor(public name: string) { + } printName(): string { @@ -13,14 +14,23 @@ abstract class Department { } -// Exercise - implement IT class which will extend Department class +class IT extends Department{ + + constructor() { + super("IT"); + } + + printMeetingName() { + return `${this.constructor.name} meeting`; + } +} describe('Class - abstract', () => { - // it('IT - use extended methods', () => { - // var it = new IT(); + it('IT - use extended methods', () => { + var it = new IT(); - // expect(it.printMeetingName()).to.equal('IT meeting'); - // }); + expect(it.printMeetingName()).to.equal('IT meeting'); + }); }); diff --git a/src/04_interfaces/interfaces_0_intro/interfaces.spec.ts b/src/04_interfaces/interfaces_0_intro/interfaces.spec.ts index eba2056..fbf9e79 100644 --- a/src/04_interfaces/interfaces_0_intro/interfaces.spec.ts +++ b/src/04_interfaces/interfaces_0_intro/interfaces.spec.ts @@ -13,106 +13,118 @@ describe('Interfaces - introduction', () => { // expect(getLabel(myObj)).to.equal('test'); // }); - // it('Required object parameter with interface', () => { + it('Required object parameter with interface', () => { - // /*Exercise - create IMyObject interface that will have same result as above*/ + interface IMyObject { + label: string, + size?: number + } - // function getLabel(labelledObj: IMyObject) { - // return labelledObj.label; - // } + function getLabel(labelledObj: IMyObject) { + return labelledObj.label; + } - // let myObj = {size: 10, label: "test"}; + let myObj = {size: 10, label: "test"}; - // expect(getLabel(myObj)).to.equal('test'); - // }); + expect(getLabel(myObj)).to.equal('test'); + }); - // it('Required object parameter with interface - with function', () => { + it('Required object parameter with interface - with function', () => { - // /*Exercise - implement missing things here*/ - // interface IMyObject { - // label: string - // } + /*Exercise - implement missing things here*/ + interface IMyObject { + label: string, + doubleText: (val: string) => string + } - // function getLabel(labelledObj: IMyObject) { - // return labelledObj.doubleText(labelledObj.label); - // } + function getLabel(labelledObj: IMyObject) { + return labelledObj.doubleText(labelledObj.label); + } - // let myObj: IMyObject = {label: "test", doubleText: (text: string) => text + text}; + let myObj: IMyObject = {label: "test", doubleText: (text: string) => text + text}; - // expect(getLabel(myObj)).to.equal('testtest'); - // }); + expect(getLabel(myObj)).to.equal('testtest'); + }); - // it('Required object parameter with interface - optional parameter', () => { + it('Required object parameter with interface - optional parameter', () => { - // interface IMyObject { - // /*Exercise - implement missing things here*/ - // } + interface IMyObject { + label: string, + size? : number + } - // function getLabel(labelledObj: IMyObject) { - // return labelledObj.label + (labelledObj.size ? labelledObj.size : ''); - // } + function getLabel(labelledObj: IMyObject) { + return labelledObj.label + (labelledObj.size ? labelledObj.size : ''); + } - // let myObj: IMyObject = {size: 10, label: "test"}; - // let myObj2: IMyObject = {label: "test"}; + let myObj: IMyObject = {size: 10, label: "test"}; + let myObj2: IMyObject = {label: "test"}; - // expect(getLabel(myObj)).to.equal('test10'); - // expect(getLabel(myObj2)).to.equal('test'); - // }); + expect(getLabel(myObj)).to.equal('test10'); + expect(getLabel(myObj2)).to.equal('test'); + }); - // it('Required object parameter with interface - with extenstion', () => { + it('Required object parameter with interface - with extenstion', () => { - // interface IMyObject { - // label: string, - // } + interface IMyObject { + label: string, + } - // /*Exercise - implement missing interface here*/ + interface IMyObjectWithSize extends IMyObject{ + size?: number + } - // function getLabel(labelledObj: IMyObjectWithSize) { - // return labelledObj.label + (labelledObj.size ? labelledObj.size : ''); - // } + function getLabel(labelledObj: IMyObjectWithSize) { + return labelledObj.label + (labelledObj.size ? labelledObj.size : ''); + } - // let myObj: IMyObjectWithSize = {size: 10, label: "test"}; - // let myObj2: IMyObject = {label: "test"}; + let myObj: IMyObjectWithSize = {size: 10, label: "test"}; + let myObj2: IMyObject = {label: "test"}; - // expect(getLabel(myObj)).to.equal('test10'); - // expect(getLabel(myObj2)).to.equal('test'); - // }); + expect(getLabel(myObj)).to.equal('test10'); + expect(getLabel(myObj2)).to.equal('test'); + }); - // it('Required object parameter with interface - index signatures', () => { + it('Required object parameter with interface - index signatures', () => { - // interface IMyObject { - // label: string, - // /*Exercise - index signature that accept only string properties*/ - // } + interface IMyObject { + label: string, + [myProp: string]: string + } - // function getLabel(labelledObj: IMyObject) { - // return labelledObj.prefix + labelledObj.label; - // } + function getLabel(labelledObj: IMyObject) { + return labelledObj.prefix + labelledObj.label; + } - // let myObj: IMyObject = {prefix: "pre-", label: "test"}; + let myObj: IMyObject = {prefix: "pre-", label: "test"}; - // expect(getLabel(myObj)).to.equal('pre-test'); - // }); + expect(getLabel(myObj)).to.equal('pre-test'); + }); - // it('Required object parameter with interface - exercise with index signatures', () => { + it('Required object parameter with interface - exercise with index signatures', () => { - // interface IMyFn { - // joinText: /*Exercise - Missing type*/ - // } + interface IMyFnBase { + [propName: string]: string; + } + + interface IMyFn { + joinText: (...parms: IMyFnBase[]) => string; + } - // let joinAllproperties: IMyFn = { - // joinText: function(...parms: /*Exercise - Missing type*/) { - // let result = ""; + + let joinAllproperties: IMyFn = { + joinText: function(...parms: IMyFnBase[]) { + let result = ""; - // for(let element of parms) { - // for(let property in element) { - // result = result + element[property]; - // } - // } - // return result - // } - // }; - - // expect(joinAllproperties.joinText({type: 'test', value: "1"}, {type: 'test', value: "2"})).to.equal("test1test2"); - // }); + for(let element of parms) { + for(let property in element) { + result = result + element[property]; + } + } + return result + } + }; + + expect(joinAllproperties.joinText({type: 'test', value: "1"}, {type: 'test', value: "2"})).to.equal("test1test2"); + }); }); \ No newline at end of file diff --git a/src/05_generics/generics_0_intro/generics.spec.ts b/src/05_generics/generics_0_intro/generics.spec.ts index 97ee721..a36b7d6 100644 --- a/src/05_generics/generics_0_intro/generics.spec.ts +++ b/src/05_generics/generics_0_intro/generics.spec.ts @@ -27,50 +27,51 @@ describe('Generics - introduction', () => { // }); - // it('Interface with two generics - exercise', () => { + it('Interface with two generics - exercise', () => { - // interface IArgOperations { - // joinToObject: /*Exercise*/ - // } + interface IArgOperations { + joinToObject: (arg: T, arg2: Y) => {arg: T, arg2: Y} + } - // class ArgOperations implements IArgOperations { + class ArgOperations implements IArgOperations { - // joinToObject = /*Exercise - should build object from two parameters with generic types*/ - // } + joinToObject = (arg: T, arg2: Y) => {return {arg, arg2}} + } - // var argOperations = new ArgOperations(); - // var results = argOperations.joinToObject('Test', 2); + var argOperations = new ArgOperations(); + var results = argOperations.joinToObject('Test', 2); - // expect(results.arg).to.equal('Test'); - // expect(results.arg2).to.equal(2); - // }); + expect(results.arg).to.equal('Test'); + expect(results.arg2).to.equal(2); + }); - // it('Interface with generic arguments - exercise', () => { - // interface IArgOperations { - // mergeParametersToArray: /*Exercise*/ - // } + it('Interface with generic arguments - exercise', () => { + interface IArgOperations { + mergeParametersToArray: (...elements: T[]) => T[] + } - // class ArgOperations implements IArgOperations { - // mergeParametersToArray = /*Exercise - should build array from any quantity of parameters, bit all must be same type*/ - - // } + class ArgOperations implements IArgOperations { + mergeParametersToArray = (...elements: T[]) => {return elements} + } - // var argOperations = new ArgOperations(); + var argOperations = new ArgOperations(); - // expect(argOperations.mergeParametersToArray('Test', 'Test2')).to.deep.equal(['Test', 'Test2']); - // expect(argOperations.mergeParametersToArray(2, 3)).to.deep.equal([2, 3]); - // }); + expect(argOperations.mergeParametersToArray('Test', 'Test2')).to.deep.equal(['Test', 'Test2']); + expect(argOperations.mergeParametersToArray(2, 3)).to.deep.equal([2, 3]); + }); - // it('Generic extending interface', () => { + it('Generic extending interface', () => { - // /*Exercise - create ILengthwise interface*/ + interface ILengthwise { + length: number; + } - // function getLength(arg: T): number { - // return arg.length; - // } + function getLength(arg: T): number { + return arg.length; + } - // expect(getLength('Test')).to.equal(4); // (change it to 2222) - // }); + expect(getLength('Test')).to.equal(4); // (change it to 2222) + }); }); \ No newline at end of file diff --git a/src/05_generics/generics_1_class/generics.spec.ts b/src/05_generics/generics_1_class/generics.spec.ts index 19de59b..64491f0 100644 --- a/src/05_generics/generics_1_class/generics.spec.ts +++ b/src/05_generics/generics_1_class/generics.spec.ts @@ -22,14 +22,17 @@ describe('Generics - classes, types, constraints', () => { // expect(genericString.value).to.deep.equal('1'); // }); - // it('Simple generics type using interface', () => { + it('Simple generics type using interface', () => { - // /*Exercise - create IGenericIdentityFn interface*/ + interface GenericIdentityFn { + (arg: T): T; + } - // let myIdentity: IGenericIdentityFn = (arg: number): number => {return arg}; + // variables with type GenericIdentityFn has to implement return their parametr + let myIdentity: GenericIdentityFn = (arg: number): number => {return arg}; - // expect(myIdentity(1)).to.equal(1); - // }); + expect(myIdentity(1)).to.equal(1); + }); // interface Person { @@ -41,13 +44,15 @@ describe('Generics - classes, types, constraints', () => { // type K1 = keyof Person; // "name" | "age" | "location" // type K2 = keyof Person[]; // "length" | "push" | "pop" | "concat" | - // it('Using Type Parameters in Generic Constraints', () => { + it('Using Type Parameters in Generic Constraints', () => { - // /*Exercise - create getProperty function that will get value by property - not allowing type non-existing properties*/ + function getProperty(obj: T, key: keyof T) { + return obj[key]; + } - // let x = { a: 1, b: 2, c: 3, d: 4 }; + let x = { a: 1, b: 2, c: 3, d: 4 }; - // expect(getProperty(x, 'b')).to.equal(2); - // //expect(getProperty(x, 'e')).to.equal(2); - that should fail - // }); + expect(getProperty(x, 'b')).to.equal(2); + //expect(getProperty(x, 'e')).to.equal(2); - that should fail + }); }); \ No newline at end of file diff --git a/src/06_enums/enums_0_intro/enums.spec.ts b/src/06_enums/enums_0_intro/enums.spec.ts index e736583..6d07c9f 100644 --- a/src/06_enums/enums_0_intro/enums.spec.ts +++ b/src/06_enums/enums_0_intro/enums.spec.ts @@ -47,37 +47,37 @@ describe('Enums - introduction', () => { // expect(Direction.Right).to.equal("RIGHT"); // }); - // it('Enum constant and computed', () => { - - // /*Exercise - make enum const*/ - // enum FileAccess { - // None, - // Read = 1 << 1, - // Write = 1 << 2, - // ReadWrite = Read | Write, - // G = "123".length, - // F = Read + Write - // } + it('Enum constant and computed', () => { + + /*Exercise - make enum const*/ + enum FileAccess { + None, + Read = 1 << 1, + Write = 1 << 2, + ReadWrite = Read | Write, + G = "123".length, + F = Read + Write + } - // expect(FileAccess.None).to.equal(0); - // expect(FileAccess.Read).to.equal(2); - // expect(FileAccess.Write).to.equal(4); - // expect(FileAccess.ReadWrite).to.equal(6); - // expect(FileAccess.G).to.equal(3); - // expect(FileAccess.F).to.equal(6); - // }); + expect(FileAccess.None).to.equal(0); + expect(FileAccess.Read).to.equal(2); + expect(FileAccess.Write).to.equal(4); + expect(FileAccess.ReadWrite).to.equal(6); + expect(FileAccess.G).to.equal(3); + expect(FileAccess.F).to.equal(6); + }); - // it('Reversed enum', () => { + it('Reversed enum', () => { - // enum MyEnum { - // A, - // B - // } + enum MyEnum { + A, + B + } - // expect(/*Exercise*/).to.equal("A"); - // expect(/*Exercise*/).to.equal("B"); - // expect(/*Exercise*/).to.equal(1); - // }); + expect(MyEnum[MyEnum.A]).to.equal("A"); + expect(MyEnum[MyEnum.B]).to.equal("B"); + expect(MyEnum[MyEnum[MyEnum.B]]).to.equal(1); + }); }); diff --git a/src/07_types_deeper/types_1_advanced/types_advanced.spec.ts b/src/07_types_deeper/types_1_advanced/types_advanced.spec.ts index 0f4fa46..1c42379 100644 --- a/src/07_types_deeper/types_1_advanced/types_advanced.spec.ts +++ b/src/07_types_deeper/types_1_advanced/types_advanced.spec.ts @@ -2,48 +2,52 @@ import { expect } from 'chai'; describe('Types - introduction', () => { - // it('Intersection types', () => { + it('Intersection types', () => { - // function extend(first: T, second: U): /*Exercise - fill type*/ { - // /*Exercise fill body*/ - // } + function extend(first: T, second: U): T & U { + return {...first, ...second}; + } - // class Person { - // name = 'PersonName'; - // } + class Person { + name = 'PersonName'; + } - // class User { - // login = 'UserLogin'; - // } - // expect(extend(new Person(), new User()).name).to.equal('PersonName'); - // expect(extend(new Person(), new User()).login).to.equal('UserLogin'); - // }); + class User { + login = 'UserLogin'; + } - // it('Union types', () => { + expect(extend(new Person(), new User()).name).to.equal('PersonName'); + expect(extend(new Person(), new User()).login).to.equal('UserLogin'); + }); - // function displayPersonAge(/*Exercise*/) : /*Exercise*/ { - // /*Exercise*/ - // } + it('Union types', () => { - // expect(displayPersonAge('Tom', 30)).to.equal('Tom: 30'); - // expect(displayPersonAge('Angela', "28")).to.equal('Angela: 28'); - // expect(displayPersonAge(undefined, "28")).to.equal(false); + function displayPersonAge(name: string | undefined, age: number | string) : string | boolean { + if(!name) return false; + return name + ": " + age; + } - // }); + expect(displayPersonAge('Tom', 30)).to.equal('Tom: 30'); + expect(displayPersonAge('Angela', "28")).to.equal('Angela: 28'); + expect(displayPersonAge(undefined, "28")).to.equal(false); + }); - // it('Custom Type guards with as', () => { - // /*Exercise - create isNumber function - test two types: boolean and type guard*/ + it('Custom Type guards with as', () => { - // let x = 10; - // if(isNumber(x)) { - // expect(x.toPrecision).not.to.equal(undefined); - // } else { - // expect(x['toPrecision']).to.equal(undefined); - // } - // }); + function isNumber(x: unknown): x is string { + return (x).toPrecision !== undefined; + } + + let x = 2; + if(isNumber(x)) { + expect(x.toPrecision).not.to.equal(undefined); + } else { + expect(x['toPrecision']).to.equal(undefined); + } + }); // it('Type guards with typeof', () => { // let x = 10; @@ -70,48 +74,50 @@ describe('Types - introduction', () => { // } // }); - // it('Nullable type - string', () => { - // let sn: string | null = "bar"; - // sn = undefined; - // sn = null; + it('Nullable type - string', () => { + let sn: string | null = "bar"; + sn = undefined; + sn = null; - // expect(sn).to.equal(/*Exercise*/); - // }); + expect(sn).to.equal(null); + }); - // it('Nullable return type', () => { - // /* Exercise - create valueOfDefault function */ + it('Nullable return type', () => { + function valueOfDefault(value: string | null | undefined) { + return value || "default"; + } - // expect(valueOfDefault('Test')).to.equal('Test'); - // expect(valueOfDefault(null)).to.equal('default'); - // expect(valueOfDefault(undefined)).to.equal('default'); - // }); + expect(valueOfDefault('Test')).to.equal('Test'); + expect(valueOfDefault(null)).to.equal('default'); + expect(valueOfDefault(undefined)).to.equal('default'); + }); // //--------------------------------------------------Exercise 1------------------------------------------------------ - // it('Type Aliases', () => { - // type Tree = /*Exercise - implement Tree type which will contain parent property and other properties from T*/ + it('Type Aliases', () => { + type Tree = T & {parent: Tree} - // class Node { - // name: string; - // } + class Node { + name: string; + } - // var node: Tree = {name: "Test", parent: {name: "ParentTest", parent: null}}; + var node: Tree = {name: "Test", parent: {name: "ParentTest", parent: null}}; - // expect(node.name).to.equal("Test"); - // expect(node.parent.name).to.equal("ParentTest"); - // }) + expect(node.name).to.equal("Test"); + expect(node.parent.name).to.equal("ParentTest"); + }) - // it('Literal type', () => { - // type Choise = /*Exercise - implement chose type which will allow only A,B,C,D*/ + it('Literal type', () => { + type Choise = 'A' | 'B' | 'C' | 'D' - // function getChoise(choise: Choise) { - // return choise; - // } + function getChoise(choise: Choise) { + return choise; + } - // expect(getChoise("A")).to.equal("A"); - // //expect(getChoise("E")).to.equal("E"); // this should throw error - // }) + expect(getChoise("A")).to.equal("A"); + //expect(getChoise("E")).to.equal("E"); // this should throw error + }) // it('Polymorphic this types', () => { // class BasicCalculator { @@ -139,50 +145,54 @@ describe('Types - introduction', () => { // }) - // it('Index types', () => { + it('Index types', () => { - // /* Exercise - Implement pluck funciton, which takes an array of property names and object, and returns an array containing the property value of object. + /* Exercise - Implement pluck funciton, which takes an array of property names and object, and returns an array containing the property value of object. - // For example: - // pluck(person, ['name', 'age']) // -> ['Jarid', 35] + For example: + pluck(person, ['name', 'age']) // -> ['Jarid', 35] - // Important - disallow type unexisting property for object for example pluck(person, ['name', '123dfsa']). Declare return type - // */ + Important - disallow type unexisting property for object for example pluck(person, ['name', '123dfsa']). Declare return type + */ - // interface Person { - // name: string; - // age: number; - // } - // let person: Person = { - // name: 'Jarid', - // age: 35 - // }; + interface Person { + name: string; + age: number; + } + let person: Person = { + name: 'Jarid', + age: 35 + }; - // let result1: string[] = pluck(person, ['name']); // change name to name2 should throw error - // let result2: (string | number)[] = pluck(person, ['name', 'age']); + function pluck(o: T, names: K[]): T[K][] { + return names.map(n => o[n]); + } - // expect(result1[0]).to.equal('Jarid'); - // expect(result2[0]).to.equal('Jarid'); - // expect(result2[1]).to.equal(35); - // }) + let result1: string[] = pluck(person, ['name']); // change name to name2 should throw error + let result2: (string | number)[] = pluck(person, ['name', 'age']); + + expect(result1[0]).to.equal('Jarid'); + expect(result2[0]).to.equal('Jarid'); + expect(result2[1]).to.equal(35); + }) // --------------------------------------------------Exercise 2------------------------------------------------------ - // it('Conditional Types', () => { - // type NonNullable = /* Exercise - implement nonNullable type that will not allow null or underfined */ + it('Conditional Types', () => { + type NonNullable = T extends null | undefined ? never : T; - // let value: NonNullable; - // value = "Test"; + let value: NonNullable; + value = "Test"; - // let value2 : NonNullable; - // // value2 = undefined; - should throw error + let value2 : NonNullable; + // value2 = undefined; - should throw error - // expect(value).to.equal("Test"); - // expect(typeof value2).to.equal('undefined'); - // }) + expect(value).to.equal("Test"); + expect(typeof value2).to.equal('undefined'); + }) // it('Conditional Types - advanced sample', () => { // /* Exercise - create Key type */ diff --git a/src/exercises/classes_interfaces/classes_intefaces_deeper2.spec.ts b/src/exercises/classes_interfaces/classes_intefaces_deeper2.spec.ts index 621e48b..92b63a5 100644 --- a/src/exercises/classes_interfaces/classes_intefaces_deeper2.spec.ts +++ b/src/exercises/classes_interfaces/classes_intefaces_deeper2.spec.ts @@ -1,28 +1,69 @@ -// import { expect } from 'chai'; +import { expect } from 'chai'; -// describe('Interfaces and classes - deeper', () => { +describe('Interfaces and classes - deeper', () => { -// it('Exercise 2', () => { -// let list = new MyList(); -// expect(list.length).to.equal(0); + it('Exercise 2', () => { + let list = new MyList(); + expect(list.length).to.equal(0); -// list.add("Element1"); -// list.add("Element2"); -// list.add("Element3"); + list.add("Element1"); + list.add("Element2"); + list.add("Element3"); -// expect(list.length).to.equal(3); -// expect(list.first()).to.equal("Element1"); -// expect(list.first()).to.equal(list.getAll()[0]); + expect(list.length).to.equal(3); + expect(list.first()).to.equal("Element1"); + expect(list.first()).to.equal(list.getAll()[0]); -// list.remove("Element2"); -// expect(list.length).to.equal(2); + list.remove("Element2"); + expect(list.length).to.equal(2); -// let listNextInstance = new MyList(list); -// expect(listNextInstance.length).to.equal(2); + let listNextInstance = new MyList(list); + expect(listNextInstance.length).to.equal(2); -// expect(list.add('NewElement').getAll().length).to.equal(3); + expect(list.add('NewElement').getAll().length).to.equal(3); -// }); -// }) + }); +}) + + +interface IMyList { + add(value: string): IMyList, + remove(value: string): IMyList, + first(): string, + getAll(): string[] +} + +class MyList implements IMyList { + + private list: string[]; + constructor (newList: MyList = null) { + if (newList) + this.list = newList.getAll(); + else + this.list = []; + } + + get length() { + return this.list.length; + } + + add(value: string): IMyList { + this.list.push(value); + return this; + } + + remove(value: string): IMyList { + const index = this.list.findIndex(item => item === value); + this.list.splice(index, 1); + return this; + } + + first(): string { + return this.list[0]; + } + getAll(): string[] { + return this.list; + } +} \ No newline at end of file diff --git a/src/exercises/generics_enums/generics_enums_deeper.spec.ts b/src/exercises/generics_enums/generics_enums_deeper.spec.ts index dafa4d4..b177765 100644 --- a/src/exercises/generics_enums/generics_enums_deeper.spec.ts +++ b/src/exercises/generics_enums/generics_enums_deeper.spec.ts @@ -1,33 +1,98 @@ -// import { expect } from 'chai'; +import { expect } from 'chai'; -// describe('Generics and enums- fundamentals exercise', () => { +describe('Generics and enums- fundamentals exercise', () => { -// it('Exercise 1', () => { -// let list = new MyList(); -// expect(list.length).to.equal(0); + it('Exercise 1', () => { + let list = new MyList(); + expect(list.length).to.equal(0); -// list.add("Element1"); -// list.add("Element2"); -// list.add("Element3"); + list.add("Element1"); + list.add("Element2"); + list.add("Element3"); -// expect(list.length).to.equal(3); -// expect(list.first()).to.equal("Element1"); -// expect(list.first()).to.equal(list.getAll()[0]); + expect(list.length).to.equal(3); + expect(list.first()).to.equal("Element1"); + expect(list.first()).to.equal(list.getAll()[0]); -// list.remove("Element2"); -// expect(list.length).to.equal(2); + list.remove("Element2"); + expect(list.length).to.equal(2); -// let listNextInstance = new MyList(list); -// expect(listNextInstance.length).to.equal(2); + let listNextInstance = new MyList(list); + expect(listNextInstance.length).to.equal(2); -// expect(list.add('NewElement').getAll().length).to.equal(3); + expect(list.add('NewElement').getAll().length).to.equal(3); -// expect(list.operation(Operation.Add, "ElementAddedWithEnum").length).to.equal(4); + //expect(list.operation(Direction.Add, "ElementAddedWithEnum").length).to.equal(4); -// expect(list.where(x=>x.indexOf('3') > 0).first()).to.equal("Element3"); + expect(list.where(x=>x.indexOf('3') > 0).first()).to.equal("Element3"); -// expect(list.addMultiple("ArgElement1", "ArgElement2").length).to.equal(6); -// }); + expect(list.addMultiple("ArgElement1", "ArgElement2").length).to.equal(5); + }); + + type filter = (filter: T) => boolean + + enum Direction { + Add, + Remove + } + + interface IMyList{ + add (value: T): MyList, + remove (value: T): MyList, + first() : T, + getAll(): T[]; + where: (expression: filter)=> MyList + } + + class MyList implements IMyList { + + private list: T[]; + + get length(): number { + return this.list.length; + } + + constructor(myList: MyList = null) { + if (myList) + this.list = myList.list + else + this.list = []; + } + + add (value: T): MyList { + this.list.push(value); + return this; + } + + // new + addMultiple(...args: T[]): MyList { + this.list = this.list.concat(args); + return this; + } + + remove (value: T): MyList { + const index = this.list.findIndex(item => item === value); + this.list.splice(index, 1); + return this; + } + + // new + where(expression: filter): MyList { + let newList = new MyList(this); + newList.list = newList.list.filter(expression); + return newList; + } + + first() : T { + return this.list[0]; + } + + getAll(): T[] { + return this.list; + } + } + +}) diff --git a/tsconfig.json b/tsconfig.json index c5b0ee0..cc91652 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,6 +10,7 @@ "noImplicitAny": true, "suppressImplicitAnyIndexErrors": true, "allowJs": true, + "noImplicitThis": true //"strictBindCallApply": true, //"strictNullChecks" : true }