moving to typescript
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
/node_modules
|
/node_modules
|
||||||
|
.gitignore
|
||||||
2
app.js
2
app.js
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
sopranoTones, altoTones, tenorTones, bassTones,
|
sopranoTones, altoTones, tenorTones, bassTones,
|
||||||
extractPitchset,
|
extractPitchset,
|
||||||
} from "./js/toneGeneration.js";
|
} from "./src/toneGeneration.js";
|
||||||
|
|
||||||
const pitchsets = [sopranoTones, altoTones, tenorTones, bassTones];
|
const pitchsets = [sopranoTones, altoTones, tenorTones, bassTones];
|
||||||
|
|
||||||
|
|||||||
54
built/app.js
Normal file
54
built/app.js
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { sopranoTones, altoTones, tenorTones, bassTones, extractPitchset, } from "./src/toneGeneration.js";
|
||||||
|
const pitchsets = [sopranoTones, altoTones, tenorTones, bassTones];
|
||||||
|
// initialize four synth voices
|
||||||
|
const soprano = new Tone.Synth().toDestination();
|
||||||
|
const alto = new Tone.Synth().toDestination();
|
||||||
|
const tenor = new Tone.Synth().toDestination();
|
||||||
|
const bass = new Tone.Synth().toDestination();
|
||||||
|
// test function for audio is armed
|
||||||
|
export const audioTest = () => {
|
||||||
|
soprano.triggerAttackRelease("C5", "16n");
|
||||||
|
alto.triggerAttackRelease("F4", "16n");
|
||||||
|
tenor.triggerAttackRelease("E4", "16n");
|
||||||
|
bass.triggerAttackRelease("G3", "16n");
|
||||||
|
};
|
||||||
|
// allows a chord to be generated with input from another function
|
||||||
|
export const soundChord = (pitches) => {
|
||||||
|
const [s, a, t, b] = pitches;
|
||||||
|
soprano.triggerAttackRelease(s, "8n");
|
||||||
|
alto.triggerAttackRelease(a, "8n");
|
||||||
|
tenor.triggerAttackRelease(t, "8n");
|
||||||
|
bass.triggerAttackRelease(b, "8n");
|
||||||
|
};
|
||||||
|
// initial test: generate a single, random chord
|
||||||
|
export const fullRandomChord = () => {
|
||||||
|
let pitches = [];
|
||||||
|
for (let voice of pitchsets) {
|
||||||
|
// finds a random index, excluding any which may already exist in the array
|
||||||
|
let index;
|
||||||
|
do {
|
||||||
|
index = Math.floor(Math.random() * 100) % voice.length;
|
||||||
|
} while (pitches.includes(voice[index]));
|
||||||
|
pitches.push(voice[index]);
|
||||||
|
console.log(voice[index]);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < pitches.length; i++) {
|
||||||
|
if (pitches[i] === pitches[i + 1]) {
|
||||||
|
console.log("CAUGHT");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
soundChord(pitches);
|
||||||
|
extractPitchset(pitches);
|
||||||
|
};
|
||||||
|
// set up transport
|
||||||
|
let clock = 0;
|
||||||
|
let slowClock = 0;
|
||||||
|
const transportStart = document.getElementById('transport-start');
|
||||||
|
let transport;
|
||||||
|
const loop = new Tone.Loop((time) => {
|
||||||
|
audioTest();
|
||||||
|
}, "8n").start(0);
|
||||||
|
loop.probability = 0.8;
|
||||||
|
transportStart.onclick = () => {
|
||||||
|
Tone.Transport.start();
|
||||||
|
};
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import { extractPitchset } from "./toneGeneration.js";
|
import { extractPitchset } from "./toneGeneration.js";
|
||||||
|
|
||||||
// interval definitions:
|
// interval definitions:
|
||||||
const intervals = {
|
const intervals = {
|
||||||
0: "unison",
|
0: "unison",
|
||||||
@@ -10,55 +9,45 @@ const intervals = {
|
|||||||
5: "perfect fourth",
|
5: "perfect fourth",
|
||||||
6: "tritone"
|
6: "tritone"
|
||||||
// all intervals beyond this invert to one of the previous intervals
|
// all intervals beyond this invert to one of the previous intervals
|
||||||
}
|
};
|
||||||
|
|
||||||
// helper functions
|
// helper functions
|
||||||
const transposePitches = (pitchNames, interval) => {
|
const transposePitches = (pitchNames, interval) => {
|
||||||
let transposed = [];
|
let transposed = [];
|
||||||
pitchNames.forEach(pitch => transposed.push((pitch + interval) % 12));
|
pitchNames.forEach(pitch => transposed.push((pitch + interval) % 12));
|
||||||
return transposed;
|
return transposed;
|
||||||
}
|
};
|
||||||
|
|
||||||
const findVector = (pitches) => {
|
const findVector = (pitches) => {
|
||||||
let sorted = pitches.sort((x,y) => x - y);
|
let sorted = pitches.sort((x, y) => x - y);
|
||||||
// sorted = sorted.filter((num, idx) => {
|
// sorted = sorted.filter((num, idx) => {
|
||||||
// return sorted.indexOf(num) === idx;
|
// return sorted.indexOf(num) === idx;
|
||||||
// });
|
// });
|
||||||
|
|
||||||
// finds each interval and logs it as a duple
|
// finds each interval and logs it as a duple
|
||||||
let intervalClasses = [];
|
let intervalClasses = [];
|
||||||
for (let i = 0; i < sorted.length; i++) {
|
for (let i = 0; i < sorted.length; i++) {
|
||||||
let j = i+1;
|
let j = i + 1;
|
||||||
|
|
||||||
// does not allow out of range values in the proceeding loop
|
// does not allow out of range values in the proceeding loop
|
||||||
if (j >= sorted.length) {
|
if (j >= sorted.length) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let thing = (sorted[j] - sorted[i]) % 6
|
let thing = (sorted[j] - sorted[i]) % 6;
|
||||||
if (!(intervalClasses.includes(thing))) {
|
if (!(intervalClasses.includes(thing))) {
|
||||||
intervalClasses.push(thing);
|
intervalClasses.push(thing);
|
||||||
}
|
}
|
||||||
j++;
|
j++;
|
||||||
} while (j < sorted.length);
|
} while (j < sorted.length);
|
||||||
}
|
}
|
||||||
|
intervalClasses = intervalClasses.sort((x, y) => x - y);
|
||||||
intervalClasses = intervalClasses.sort((x,y) => x-y);
|
|
||||||
return intervalClasses;
|
return intervalClasses;
|
||||||
}
|
};
|
||||||
|
|
||||||
// analysis
|
// analysis
|
||||||
let dMajor = extractPitchset(["D", "F#", "A", "D"]);
|
let dMajor = extractPitchset(["D", "F#", "A", "D"]);
|
||||||
const eMajor = transposePitches(dMajor, 2);
|
const eMajor = transposePitches(dMajor, 2);
|
||||||
console.log(eMajor);
|
console.log(eMajor);
|
||||||
console.log('');
|
console.log('');
|
||||||
|
|
||||||
let dMajVector = findVector(dMajor);
|
let dMajVector = findVector(dMajor);
|
||||||
console.log(dMajVector);
|
console.log(dMajVector);
|
||||||
|
let complexVector = findVector([0, 3, 4, 7, 8, 11]);
|
||||||
let complexVector = findVector([0,3,4,7,8,11]);
|
|
||||||
console.log(complexVector);
|
console.log(complexVector);
|
||||||
|
let splitThird = findVector([0, 3, 4, 7]);
|
||||||
let splitThird = findVector([0,3,4,7]);
|
|
||||||
console.log(splitThird);
|
console.log(splitThird);
|
||||||
52
built/src/inputHandling.js
Normal file
52
built/src/inputHandling.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import { audioTest, fullRandomChord } from '../app.js';
|
||||||
|
// slider variables referring to DOM
|
||||||
|
export const sopranoVol = document.getElementById('soprano-vol');
|
||||||
|
const sopranoVolTarget = document.getElementById('soprano-vol-target');
|
||||||
|
export const sopLFO = document.getElementById('sop-lfo');
|
||||||
|
const sopLFOTarget = document.getElementById('sop-lfo-target');
|
||||||
|
export const altoVol = document.getElementById('alto-vol');
|
||||||
|
const altoVolTarget = document.getElementById('alto-vol-target');
|
||||||
|
export const altoLFO = document.getElementById('alto-lfo');
|
||||||
|
const altoLFOTarget = document.getElementById('alto-lfo-target');
|
||||||
|
export const tenVol = document.getElementById('ten-vol');
|
||||||
|
const tenVolTarget = document.getElementById('ten-vol-target');
|
||||||
|
export const tenLFO = document.getElementById('ten-lfo');
|
||||||
|
const tenLFOTarget = document.getElementById('ten-lfo-target');
|
||||||
|
export const bassVol = document.getElementById('bass-vol');
|
||||||
|
const bassVolTarget = document.getElementById('bass-vol-target');
|
||||||
|
export const bassLFO = document.getElementById('bass-lfo');
|
||||||
|
const bassLFOTarget = document.getElementById('bass-lfo-target');
|
||||||
|
// logic for displaying values on HTML labels
|
||||||
|
// S
|
||||||
|
sopranoVol.oninput = (e) => {
|
||||||
|
sopranoVolTarget.innerHTML = e.target.value;
|
||||||
|
};
|
||||||
|
sopLFO.oninput = (e) => {
|
||||||
|
sopLFOTarget.innerHTML = ` ${e.target.value} Hz.`;
|
||||||
|
};
|
||||||
|
// A
|
||||||
|
altoVol.oninput = (e) => {
|
||||||
|
altoVolTarget.innerHTML = e.target.value;
|
||||||
|
};
|
||||||
|
altoLFO.oninput = (e) => {
|
||||||
|
altoLFOTarget.innerHTML = ` ${e.target.value} Hz.`;
|
||||||
|
};
|
||||||
|
// T
|
||||||
|
tenVol.oninput = (e) => {
|
||||||
|
tenVolTarget.innerHTML = e.target.value;
|
||||||
|
};
|
||||||
|
tenLFO.oninput = (e) => {
|
||||||
|
tenLFOTarget.innerHTML = ` ${e.target.value} Hz.`;
|
||||||
|
};
|
||||||
|
// B
|
||||||
|
bassVol.oninput = (e) => {
|
||||||
|
bassVolTarget.innerHTML = e.target.value;
|
||||||
|
};
|
||||||
|
bassLFO.oninput = (e) => {
|
||||||
|
bassLFOTarget.innerHTML = ` ${e.target.value.toString()} Hz.`;
|
||||||
|
};
|
||||||
|
// audio-adjacent input handling
|
||||||
|
const synthButton = document.getElementById('synth-button');
|
||||||
|
synthButton.onclick = audioTest;
|
||||||
|
const randChord = document.getElementById('rand-chord');
|
||||||
|
randChord.onclick = fullRandomChord;
|
||||||
44
built/src/styleUtils.js
Normal file
44
built/src/styleUtils.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
export const startButton = document.getElementById("start-tone");
|
||||||
|
export const synthButton = document.getElementById("synth-button");
|
||||||
|
export const showStart = document.getElementsByClassName('show-on-start');
|
||||||
|
export const hideStart = document.getElementsByClassName('hide-on-start');
|
||||||
|
export const showMore = document.getElementById('info-button');
|
||||||
|
export const moreInfo = document.getElementsByClassName('more-info');
|
||||||
|
export let appReady = false;
|
||||||
|
showMore.onclick = () => {
|
||||||
|
if (showMore.innerHTML === 'Show more info...') {
|
||||||
|
for (let element of moreInfo) {
|
||||||
|
element.style.display = 'block';
|
||||||
|
document.querySelector('#info-button').innerHTML = "Hide info";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (showMore.innerHTML === 'Hide info') {
|
||||||
|
for (let element of moreInfo) {
|
||||||
|
element.style.display = 'none';
|
||||||
|
document.querySelector('#info-button').innerHTML = "Show more info...";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
startButton.onclick = () => __awaiter(void 0, void 0, void 0, function* () {
|
||||||
|
yield Tone.start()
|
||||||
|
.then(() => {
|
||||||
|
appReady = true;
|
||||||
|
synthButton.style.display = "block";
|
||||||
|
startButton.style.display = "none";
|
||||||
|
for (let element of showStart) {
|
||||||
|
element.style.display = "flex";
|
||||||
|
}
|
||||||
|
for (let element of hideStart) {
|
||||||
|
element.style.display = "none";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
28
built/src/toneGeneration.js
Normal file
28
built/src/toneGeneration.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// we start with a selection of pitches that generally work okay together
|
||||||
|
export const sopranoTones = ["B5", "A5", "G5", "F#5", "F5", "E5", "D5", "C5", "B4", "Bb4", "A4", "G4", "F#4", "F4", "E4"];
|
||||||
|
export const altoTones = ["E5", "D5", "C5", "B4", "Bb4", "A4", "G4", "F#4", "F4", "E4", "D4", "C4", "B3", "Bb3", "A3", "G3"];
|
||||||
|
export const tenorTones = ["G4", "F#4", "F4", "E4", "D4", "C4", "B3", "Bb3", "A3", "G3", "F3", "E3", "D3", "C3"];
|
||||||
|
export const bassTones = ["C2", "D2", "E2", "F2", "G2", "A2", "Bb2", "B2", "C3", "D3", "E3", "F3", "G3"];
|
||||||
|
// now we define some rules to allow for the program to follow so it can some basic tenets of music theory
|
||||||
|
// we're going to include all pitches, so that it can use semitone-based pitch logic.
|
||||||
|
// this is focused on base-12, something computers understand quite well
|
||||||
|
const musicalPitches = ['A', "Bb", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"];
|
||||||
|
export const extractPitchset = (pitches) => {
|
||||||
|
// 1) determine pitch set from given array of pitches
|
||||||
|
let pitchset = [];
|
||||||
|
for (let each of pitches) {
|
||||||
|
// filters numbers from above tones
|
||||||
|
const str = each;
|
||||||
|
const regex = /[0-9]/g;
|
||||||
|
const withoutNums = str.replace(regex, '');
|
||||||
|
const pitchNumber = musicalPitches.indexOf(withoutNums);
|
||||||
|
// ... so that they may be mapped onto numbers corresponding to the chromatic scale
|
||||||
|
pitchset.push(pitchNumber);
|
||||||
|
}
|
||||||
|
// these are sorted from lowest to highest index (something like an interval vector)
|
||||||
|
pitchset.sort((a, b) => a < b);
|
||||||
|
console.log(pitchset);
|
||||||
|
return pitchset;
|
||||||
|
};
|
||||||
|
// no tritones
|
||||||
|
// no minor 2nds or major 7ths
|
||||||
@@ -118,9 +118,9 @@
|
|||||||
<!-- Tone.js library -->
|
<!-- Tone.js library -->
|
||||||
<script type="module" src="https://unpkg.com/tone@14.7.77/build/Tone.js"></script>
|
<script type="module" src="https://unpkg.com/tone@14.7.77/build/Tone.js"></script>
|
||||||
<!-- internal scripts -->
|
<!-- internal scripts -->
|
||||||
<script type="module" src="./js/inputHandling.js"></script>
|
<script type="module" src="./src/inputHandling.js"></script>
|
||||||
<script type="module" src="./js/toneGeneration.js"></script>
|
<script type="module" src="./src/toneGeneration.js"></script>
|
||||||
<script type="module" src="./js/styleUtils.js"></script>
|
<script type="module" src="./src/styleUtils.js"></script>
|
||||||
<script type="module" src="app.js"></script>
|
<script type="module" src="app.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
20
package-lock.json
generated
20
package-lock.json
generated
@@ -9,7 +9,8 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tone": "^14.7.77"
|
"tone": "^14.7.77",
|
||||||
|
"typescript": "^4.6.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/runtime": {
|
"node_modules/@babel/runtime": {
|
||||||
@@ -63,6 +64,18 @@
|
|||||||
"version": "2.4.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
||||||
|
},
|
||||||
|
"node_modules/typescript": {
|
||||||
|
"version": "4.6.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz",
|
||||||
|
"integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==",
|
||||||
|
"bin": {
|
||||||
|
"tsc": "bin/tsc",
|
||||||
|
"tsserver": "bin/tsserver"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.2.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -111,6 +124,11 @@
|
|||||||
"version": "2.4.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
||||||
|
},
|
||||||
|
"typescript": {
|
||||||
|
"version": "4.6.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz",
|
||||||
|
"integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,14 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"main": "app.js",
|
"main": "app.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"build": "tsc -p ."
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tone": "^14.7.77"
|
"tone": "^14.7.77",
|
||||||
|
"typescript": "^4.6.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
64
src/harmonyUtil.ts
Normal file
64
src/harmonyUtil.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import { extractPitchset } from "./toneGeneration.js";
|
||||||
|
|
||||||
|
// interval definitions:
|
||||||
|
const intervals = {
|
||||||
|
0: "unison",
|
||||||
|
1: "minor second",
|
||||||
|
2: "major second",
|
||||||
|
3: "minor third",
|
||||||
|
4: "major third",
|
||||||
|
5: "perfect fourth",
|
||||||
|
6: "tritone"
|
||||||
|
// all intervals beyond this invert to one of the previous intervals
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper functions
|
||||||
|
const transposePitches = (pitches: number[], interval: number) => {
|
||||||
|
let transposed = [];
|
||||||
|
pitches.forEach(pitch => transposed.push((pitch + interval) % 12));
|
||||||
|
return transposed;
|
||||||
|
}
|
||||||
|
|
||||||
|
const findVector = (pitches: number[]) => {
|
||||||
|
let sorted = pitches.sort((x,y) => x - y);
|
||||||
|
// sorted = sorted.filter((num, idx) => {
|
||||||
|
// return sorted.indexOf(num) === idx;
|
||||||
|
// });
|
||||||
|
|
||||||
|
// finds each interval and logs it as a duple
|
||||||
|
let intervalClasses: number[] = [];
|
||||||
|
for (let i = 0; i < sorted.length; i++) {
|
||||||
|
let j = i+1;
|
||||||
|
|
||||||
|
// does not allow out of range values in the proceeding loop
|
||||||
|
if (j >= sorted.length) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
let thing: number = (sorted[j] - sorted[i]) % 6
|
||||||
|
if (!(intervalClasses.includes(thing))) {
|
||||||
|
intervalClasses.push(thing);
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
} while (j < sorted.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
intervalClasses = intervalClasses.sort((x,y) => x-y);
|
||||||
|
return intervalClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
// analysis
|
||||||
|
let dMajor = extractPitchset(["D", "F#", "A", "D"]);
|
||||||
|
const eMajor = transposePitches(dMajor, 2);
|
||||||
|
console.log(eMajor);
|
||||||
|
console.log('');
|
||||||
|
|
||||||
|
let dMajVector = findVector(dMajor);
|
||||||
|
console.log(dMajVector);
|
||||||
|
|
||||||
|
let complexVector = findVector([0,3,4,7,8,11]);
|
||||||
|
console.log(complexVector);
|
||||||
|
|
||||||
|
let splitThird = findVector([0,3,4,7]);
|
||||||
|
console.log(splitThird);
|
||||||
8
tsconfig.json
Normal file
8
tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./built",
|
||||||
|
"allowJs": true,
|
||||||
|
"target": "es2016"
|
||||||
|
},
|
||||||
|
"include": ["./src/**/*"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user