Use PropertyKey
in a type where I need string | number | symbol
const myConstant: (A|B)[] = [instanceOfA, instanceOfB]
Type a void to void function as follows:
const x: () => void = () => {}
x()
Type a boolean to void function:
const x: (y: boolean) => void = (y) => {}
x(true)
Type a void to boolean function:
const x: () => boolean = () => { return true }
x()
const isSolid = (paint: Paint): paint is SolidPaint => paint.type === "SOLID"
const back = figma.currentPage.backgrounds.find(isSolid)
Actually, don’t do that. Do this:
https://www.typescriptlang.org/docs/handbook/advanced-types.html
[]
is truthy, e.g. !![] => true
Do not install ctags
. Install universal-ctags
instead.
const firstChar = “my string”.slice(0,1)
Set breakpoint in source with debugger
Kick off script with node inspect ...
Most shortcuts are the same as pdb, except:
Use p <expr>
instead of symbol name directly
Examples to follow:
https://stackoverflow.com/a/60007123/143447
https://stackoverflow.com/a/60448657/143447
https://jestjs.io/docs/mock-functions
Helpful matchers:
- toHaveBeenCalledTimes(1)
- toBeCalledWith(myParams)
interface X {
y?: number
}
var x: X = {y: 1}
delete x.y
I add noUnusedLocals
as a compilation flag in tsconfig.json
.
The only downside is the ts-node
repl becomes unusable.
Fix by invoking ts-node
with
ts-node -O '{"noUnusedLocals": false}'
Source: Stackoverflow comment
Use the extends
keyword. Read it as ‘satisfies’ in this case (there is really no extending happening):
function myFn<T extends TypeA|TypeB>(...)
Here is an attempt to generically filter a heterogenous array by a type
supplied by the caller. I may return to it:
// Creates a heterogenous array of Xs and Ys, and attempts to write
// a generic selector to discriminate out Xs in a type-safe way.
interface X {
type: 'x'
}
interface Y {
type: 'y'
}
type Sum = X | Y
function select<T extends Sum, U extends 'x' | 'y'>(list: Array<Sum>, u:U): Array<T> {
// I would expect this to throw a compile time error for callers where
// T and U are mismatched.
const dummy: T['type'] = u
const isDesiredType = (h: Sum): h is T => h.type === u
return list.filter(isDesiredType)
}
var myList: Array<X|Y> = [{type: 'x'}, {type: 'y'}]
// This works, yay!
const xs: Array<X> = select(myList, 'x')
// This does not throw a compile time error:
const ys: Array<Y> = select(myList, 'x')
// Error ------ ^ ------------------ ^
https://www.typescriptlang.org/docs/handbook/advanced-types.html
interface X {
a: number
}
is mostly the same as:
type X = {
a: number
}
The only difference is type X
can’t be reopened.
The a
member is optional in this definition:
type X = {
a?: number
}
This is different than:
type Y = {
a: number | null
}
Observe:
const x: X = {} # => ok
const y: Y = {} # => Property 'a' is missing in type '{}' but required in type 'Y'
I figured out a way to write test factories in a way that I’m happy with.
Say you have some interface X that requires many members to satisfy the contract.
I want my unit tests to only concern themselves with a small set of members (ideally 1).
So I create factories that will vend objects that satisfy the contract,
where the caller can manipulate a single member at a time.
It looks a bit like using named arguments from other languages, which makes the unit test readable.
As an example, X is a dependency type; I define XPrime
and factory
in factories.ts:
interface X {
a: string
b: number
}
interface XPrime {
a?: string
b?: number
}
function factory({a, b}: XPrime = {}): X {
return {
a: a || "hello",
b: b || 123
}
}
Then I can get instances of X in a unit test with factory()
, or factory({a: "hi"})
or factory({b: 0})
.
If I don’t supply a
or b
they default to values of hello
and 123
, respectively.
function x(a: string = "hello") {
console.log(a)
}
const x = {'a': 'foo', 'b': 'bar'}
const y = {'b': 'BAZ'}
{ ...x, ...y}
# => {'a': 'foo', 'b': 'BAZ'}
[1,2,null,undefined,3].filter((x) => x)
or
import { compact } from 'lodash'
compact([1,2,null,undefined,3])
or
[1,2,null].filter(Boolean)
[1,2,3].find((x) => x == 2)
Use console.debug
, console.warn
, console.error
.
Also, log like this: console.log({myThing})
.
Other tips here: https://dev.to/ackshaey/level-up-your-javascript-browser-logs-with-these-console-log-tips-55o2
console.assert(condition, "expected <condition> to be met")
https://www.typescriptlang.org/cheatsheets
tsconfig.json is not read when tsc is passed a specific file. E.g. tsc
myfile.ts will not consider tsconfig.json.
myObj.constructor.name
If npx ts-node
is taking a few seconds to start, and doesn’t start at all
without internet connection, it’s because I forgot npm install --save-dev ts-node
function addN(n: number) {
return function(x: number) {
return x + n
}
}
const y = addN(3)
y(2) # returns 5
function foo(): [string, string] {
return ['hi', 'ho']
}
let [x, y] = foo()
function foo() {
let x = 1
function bar() {
return x
}
x += 1
return bar
}
console.log(foo()())
/^[a-z]$/i.test('A')
source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
Also see match
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match
if (foo == null) {
// `foo` is null or undefined
}
source: https://stackoverflow.com/a/70040699/143447
expect(() => parse(lex('(+ 1 world)').tokens())).toThrow(/ParseError on bad expression/)
class ParseError extends Error {}
new MyClass()
throw new ParseError("this is an error")
class Foo {
x: number
constructor(x: number) {
this.x = x
}
}
class A {
b(): string {
return "hello world"
}
}
const x = 'world'
`hello ${world}`
const x = 'hello'
x.slice(<start-index>, <end-index>)
const x = [1,2,3]
x.map(y => y + 1)
Math.max(<a>, <b>)
Math.min(<a>, <b>)
[1,2,3].join(',')
"hello".repeat(2)
`hello
world`
If indented, the above will contain whitespace before ‘world’. An alternative:
'hello\n' +
'world'