Javascript's Unary Plus Operator
Today I learned about the unary plus (+
) operator. It attempts to convert its operand into a number, so it's basically a shorthand for Number()
(and uses the same rules around number coercion).
Today I learned about the unary plus (+
) operator. It attempts to convert its operand into a number, so it's basically a shorthand for Number()
(and uses the same rules around number coercion).
TypeScript has an Omit utility type that lets you create a new type by excluding specific keys from an existing type. It's perfect for cases where you need a type that's almost the same but without certain properties.
Here's an example:
Now we have a PublicUser
type that includes id and name, but the password field is excluded.
I'm very used to ruby's gsub(pattern, replacement)
that does a [g]lobal [sub]stitution on a string - that is, it replaces all occurrences of the pattern in the string. If you wanted to just replace the first occurrence of the pattern you could use sub
, but I so rarely need to do that I forgot it existed.
Javascript's equivalent, replace
, handles things a little bit differently. So much so I was surprised by it's behavior.
pattern
can be a string
or a RegExp
, but you get different replacement behavior depending on which you use.
pattern
is a string, only the first occurrence of pattern
will be replaced. pattern
is a RegExp
, by default it will replace the first occurrence, unless you pass the global flag to the pattern. So if I wanted to replace asdf
in with hjkl
in a string, replace(/asdf/, "hjkl")
will replace just the first occurrence. To replace all occurrences, it needs to be replace(/adsf/g, "hjkl)
(note the global g
flag in the regex). So maybe the moral of the story is to always use a regex (and remember your flags!).
Stimulus.js controllers are great! However, sometimes you need to trigger them in different ways. Usually, you're looking at an event on an element.
Now, this is a trivial example as the Textarea-Autogrow controller is already monitoring the element without the need for the explicit data-action
above.
In my case, I'm also using this text area within a tab powered by another controller from the Tailwind Stimulus Components library called Tabs. Due to the tab hiding my text area at the time of rendering, it doesn't calculate the height of the content inside. I'll need to trigger this manually. Luckily, the Tab controller emits a tsc:tab-change
event on the window
.
Now, I can utilize this on my textarea
with the @window
syntax.
This way, we trigger the autogrow
function with each element's input and when we change tabs.
Check out the Global Events documentation for more info.
A browser's visibilityState
property is an essential aspect of web development that plays a crucial role in optimizing user experience and resource management in web applications. This property is part of the Page Visibility API, a web standard that provides developers with the ability to determine the current visibility state of a webpage.
The concept of visibility state revolves around whether a webpage is in a "visible" or "hidden" state. When a user navigates to a different tab, minimizes the browser window, or locks the screen, the webpage becomes "hidden". Conversely, when the webpage is in the foreground, and the user actively interacts with it, the state is "visible".
In npm
v6 and below, npm audit
has a --parseable
option that will output
the audit report in plain text rows with tab delimiters. By default its a lot
of information, but you can awk
and grep
/ripgrep
to parse and filter down
to what you want.
To only print the package name, vulnerability level and resolution, you can run:
% npm audit --parseable | awk -F $'\t' '{print $2, $3, $4}'
minimist critical npm update minimist --depth 15
immer high npm install react-scripts@5.0.1
loader-utils high npm install react-scripts@5.0.1
decode-uri-component high npm install react-scripts@5.0.1
And you can pipe that through to ripgrep
to only show the critical
vulnerabilities.
% npm audit --parseable | awk -F $'\t' '{print $2, $3, $4}' | rg critical
minimist critical npm update minimist --depth 15
In newer versions of npm
, the --parseable
option was dropped and instead you
can use the --json
option to output to json instead.
Using skip
in Jest tests is a valuable technique for temporarily disabling specific tests without completely removing them from your test suite. This is particularly useful during development when you focus on one particular feature or bug and want to avoid running unrelated tests to save time. In Jest, you can use skip
by prefixing it to your test or describe blocks.
For instance, test.skip(...)
or describe.skip(...)
will skip the execution of the specified test or group of tests. This approach is much more maintainable than commenting out tests, as it keeps the test code intact and easily readable.
Moreover, skipped tests are reported in Jest's output, reminding you that there are tests that need attention. This feature is convenient when working in a team environment, as it allows developers to be aware of tests that are not currently active but are still part of the overall test plan. It also helps ensure that all tests are eventually re-enabled and the test coverage remains comprehensive.
In TypeScript, the Pick
utility type provides a flexible way to construct new types by selecting subsets of properties from existing ones. For example, consider an interface User
:
In this example, UserContactDetails
is a new type with only the email
and name
properties from the User
interface.
This is particularly beneficial when you must pass or manipulate only specific aspects of a complex type, ensuring type safety and reducing the risk of handling unnecessary or sensitive data. By tailoring types to particular use cases, Pick
enhances code maintainability and readability, streamlining development processes in TypeScript applications.
Suppose you import two functions from an external library in one of your js files:
Now let's write a test for this function, and say we want to mock func1
.
But oh no! This test will fail - we inadvertently blew away the rest of the implementation of externalLib
when we created the mock for func1
. Since doSomething
relies on other functions in externalLib
, we get errors.
In order to preserve the rest of the implementation of externalLib
and only mock func1
, we need to call requireActual and spread it's return into the mock to get the implementation of the rest of the library:
Et voilà, your test will pass ✅.
Jest runs tests in parallel by default, file by file.
That means if you add a .only
on an it
or describe
, that only applies in the context of a single file. So if you have a test suite with 5 different test files and execute tests with jest
, 4 test files will run all their tests and one file will run it's only
test.
If you want only a single test to run, you need to add that .only
and narrow jest's scope to that single test file: jest src/path/to/test.js
.
Say you have a few unused imports in your JS file:
If you're using Visual Studio Code (or a forked version like Cursor) you can press Option/Alt
+Shift
+O
to remove all unused imports.
Note: this also sorts your current imports
In a Node.js project, versions of Node that a project is compatible with can be declared using the "engines" key within the package.json
file. To set a specific Node version (or a range of versions), you'll use the node
property inside the engines
object.
For example, to specify that your project is compatible with Node version 14.15.1, you would include the following:
If you want to indicate compatibility with various versions, you can use semantic versioning notation. For instance, "node": ">=14.0.0 <15.0.0"
means your project is compatible with versions of Node greater than or equal to 14.0.0 but less than 15.0.0. By setting the engines
key, you hint to other developers and deployment platforms about which Node versions should be used with your project. Note, however, that unless you use a package manager that enforces this (e.g., Yarn or newer versions of npm), this is primarily advisory and won't prevent the project from running on non-specified versions.
Importing a module can be lengthy, depending on your project's app structure.
Utilizing your tsconfig
, aliases can be created for module resolution.
Now, our previous example can be expressed like so:
Next.js is already set up to deal with this, so you should not need to add any additional libraries like tsc-alias
to handle the actual module resolution when the project is built for production.
When working with command-line tools, it's common to encounter scenarios where you'd like to test or run a tool without committing to a global installation, especially for one-off tasks. The npx utility addresses this exact need. By invoking npx <command>
, the tool automatically fetches and installs the package corresponding to <command> from the npm registry if it's not already in your $PATH
. This allows you to execute the desired command seamlessly. A significant advantage is that post-execution, npx
ensures the package is not retained as a global installation, preventing unnecessary clutter or "pollution" in your global packages. This utility offers a cleaner, transient approach to testing and using CLI tools.
Usually you structure your graphql queries and mutations in a way that the cache just works out of the box. But there are times that you need to manually update the graphql cache then you can call updateQuery
:
Note that the return
is optional, so if your update function returns undefined
then it will keep the cache intact, without updating anything.
When writing script commands in your package.json
you can have additional scripting before & after your script with a special incantation of script commands.
Say you have a test
script
If you want to add a prerunner you just need to append the text pre
to your command.
As you may have expected by now you'll do the same to get scripting after your command.
This all happens via a naming scheme, so just remember pre
& post
.
More info in the documentation.
Need to debug a test in Jest but can't figure out how? Or possibly you have a react-native app and you can't figure out how to debug a component?
Run jest via the node
command so that the flag of --inspect-brk
can be added.
node --inspect-brk ./node_modules/jest/bin/jest.js --runInBand
From the docs:
The
--runInBand
cli option makes sure Jest runs the test in the same process rather than spawning processes for individual tests. Normally Jest parallelizes test runs across processes but it is hard to debug many processes at the same time.
Then open your chromium based browser (chrome, brave, etc...) and go to about:inspect
. This will open the dev tools where you can select 'Open dedicated DevTools for Node'.
Then you'll see the node dev tools window open.
Now just enter a debugger whereever you need and run the jest command from above.
If you need to hijack an input's cursor position, you can use .setSelectionRange()
. This function takes two zero-based index arguments: a starting position and end position and makes makes a text-selection based on those start and end points. With this understanding, we can pass in the same index for both the start and end point to manually move the cursors position without making a selection. For example:
In javascript you can use the Number.toLocaleString()
function to format the number correctly with commas. All you need is the BCP 47 language code to specify how to format the number (some countries/languages use periods instead of commas). It works like this:
You can install a specific version of a package with yarn add
. To add enzyme
at version 1.2.3 you can:
$ yarn add enzyme@1.2.3
You can also specify a git repository (including branch):
$ yarn add enzyme@enzymejs/enzyme#branch-name
You can check if a form passes HTML validations with javascript using the checkValidity
function:
In javascript, the Array sort function will cast everything to a string. So when you have an array of numbers, you need to repetitively cast them to numbers:
So you need have to write your own sort function (don't mess it up!)
🐉
Jest allows you to view test coverage when it runs.
But even if I only run tests for a specified file or files, the --coverage
output will include all files.
$ jest src/directoryToTest --coverage
If your app is large, this can generate a lot of output and be difficult to parse. If I only care about the coverage for files in directoryToTest
, I can filter the output of --coverage
with --collectCoverageFrom=
:
$ jest src/directoryToTest --coverage --collectCoverageFrom="src/directoryToTest/**"
In TypeScript you can build your own custom object types. Custom types work just like any other type. You can use it like this:
If you define a vehicle without any of the required types, TypeScript will provide an error stating which property is missing from the object. For example:
This definition will provide an error Property 'capacity' is missing in type '{ make: string; model: string; }' but required in type 'Vehicle'.
, because the capacity property is missing.
Today I learned that you can make a class function to be private by prefixing it with a #
. Check this out:
We can also use that trick to make static methods, fields or static fields as well.
Thanks Andrew Vogel for this tip 😁
Javascript offers desctructuring assignment for array values and object properties. The syntax works like this:
Very handy
Javascript arrays have a function called some
that can be used to determine if at least one element of an array passes a test:
Exceptions caught in a try/catch
are not guaranteed to be an instance of Error
class, or a child of Error
. The exception caught can be anything - an object of any type, string, number, null... you name it.
So in typescript, the compiler won't like:
The typescript compiler can't infer the type of e
, so defaults the type to unknown
. If you know your error will have a message, you can do something like this:
The window
object has a great API for working with screens(mobile devices, etc) and their related metadata - window.screen
and window.screen.orientation
.
For Mobile Devices and Full Screen browsers, you can use the following methods to toggle orientation locks:
Note that when you call the lock API on a web browser that is not full screen, it will raise a DOMException
similar to following:
DOMException: screen.orientation.lock() is not available on this device.
Acceptable orientation values can be found in the docs linked below
https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation/lock
I'm sure you're already familiar with console.log()
to debug, but did you know that there is a similar console.table()
that is great for displaying arrays and objects?
Here are some examples,
Assuming you had an array of names
Assuming you had a person object
Assuming you had an array of person objects
There is also an optional columns
parameter, which takes an array containing the names of columns you want to include in the output.
console.table(data)
console.table(data, columns)
Due to security reasons what can be received from an iFrame can be very limited. However there is a utility built for the purpose of safely communicating with things like an iFrame, pop-up, etc.
An iframe can utilize the Window.postMessage()
function to post info that may be relevant to someone embedding the iFrame.
Then in the page where the embedded iFrame is located, the message
event can be watched.
By utilizing the event's origin
you can be even safer. Above we're declaring that if the origin of tghe event did not come from the expected iframe's url... just stop.
If you're good with the origin check then looks at the event's data
property. It will provide whatever was sent via postMessage()
.
If you want to set an event listener on document for an input's onFocus
event, you'll find there is no "onFocus" event for document
. Instead you can use the focusin
event listener:
So if you had dynamic events you can achieve this:
When working with form names, it's nice to have typescript support:
In this example, we need to put placeholder values on global.window to allow us to use Ruby on Rails' ActionCable websocket framework where no window exists:
But we need to add a type:
Today I Learned that you need to be careful when working with numbers in JavaScript. This is because of the way that JavaScript implements the Number type.
The JavaScript Number type is a double-precision 64-bit binary format IEEE 754 value, like double in Java or C#. This means it can represent fractional values ...
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number
Take for example the following Ruby snippet:
Our division here returns 0, which is what I expected. And if you want the remainder, you can get it with the modulus operator %
Now here's the same snippet in JavaScript, which returns a double-precision number that is not zero
If you're looking to do integer-like division in JavaScript, here's a few ways you can accomplish that:
Docs
Here's a callback to another JavaScript number TIL 😅
https://til.hashrocket.com/posts/e04ffe1d76-because-javascript
Next.js has a handy feature for rendering a child component client side, instead of on the server.
Consider the following example, where you have a component in src/components/Analytics.js
with a default
export.
You can also use this dynamic importing feature with named exports. Consider the next example:
There are some gotcha's when using dynamic
, so make sure to check out the docs and get familiar with the API.
https://nextjs.org/docs/advanced-features/dynamic-import
I was trying to see if I could find a lodash
method that works the same way as index_by from ruby
and I found keyBy:
Funny thing is that on a previous version of lodash
this method was called indexBy, same as the ruby version.
You can utilize 'private' features in a javascript class via the #
character prepending a name. They are referred to as 'hash names'.
These private fields must be declared ahead of time otherwise they will result in a syntax error.
For this example I replaced some declaratively 'private' attributes _closed
& _balance
with actual 'private' attributes #closed
& #balance
.
It appears that if you're at Node 12 or higher you can use this functionality.
You can read more about this at MDN
Ever need to have a back up default value when something is null
or undefined
in Javascript? Well a fairly recent addition to JS has got you covered. The Nullish coalescing operator ??
may help you on your logical path.
If the first half of the epresssion is 'nullish', it will return the latter.
compare this to using ||
in which the first half of expression needs to evaluate falsey to get into the latter portion.
As it is a newer part of the JS API make sure to check for browser support. There is also a polyfill available.
Cleaning up a test suite and getting a lot of cryptic UnhandledPromiseRejectionWarning:
s? Well then this little snippet can save you some time:
Today I got a chance to try out the TypeScript union type. It looks like this.
This lets me tell consumers of FlashMessageInterface
that it is allowed to have two shapes: one with a state
key of success
and one with a state
key of failure
. I can use this to change how I present the flash message.
Sometimes I just want to blow away a JavaScript library's versioning in the lockfile and go to the latest. This happens with projects still in development or requiring very stable libraries– I want to be on latest now, rather than creeping up the semantic versioning ladder. Here's how this is done with Yarn.
$ yarn upgrade --latest react
Enjoy the latest features.
Here's some fun code:
Notice the object inside className
– what's going on here?
This is a dynamic class name via ES2015+ computed keys. If appClass
is provided as a truthy prop, the class is enabled; if it is not provided or provided as a falsy prop, the class is not enabled.
If you don't need an element in an array while destructuring it, simply omit a name:
When writing a Jest test, the setup code inside any top-level describe
function gets run before any scenario. So, if you setup a world in one describe
, and a competing world in another, the last one that is run wins.
This even applies when you've marked a describe as 'skip' via xdescribe
. The code inside that setup will still be run.
This is a first pass at a TIL, because I'm not sure the behavior I'm seeing is expected, and if so, why it is expected. It certainly surprised me 😳. I think one solution is to limit your tests to one top-level describe
which has the important benefit of being more readable, too.
Immutablejs doesn't work very well with typescript. But I can patch types myself for some perceived type safety:
The "non-null assertion operator" or "!" at the end of an operand is one way to tell the compiler you're sure the thing is not null, nor undefined. In some situations, the compiler can't determine things humans can.
And we're cranking out some code that tells us if
Obviously we are checking if the map has gold first. If it doesn't, the execution returns early with false. If it does, then we know we can safely access the value.
But the compiler gets really upset about this:
Object is possibly 'undefined'. ts(2532)
In this case, the compiler doesn't keep map.has(treasure)
in context when evaluating map.get(treasure)
. There is more than one way to solve this, but for now we can simply "assert" our superiority over the compiler with a bang.
Today while doing an Exercism, I learned that through ES6 destructuring we can swap two array items in one line of code. Here's how it works:
Items one and two are swapped in array
. Modify those values in-place like a boss.