// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`convert HTML to markdown with codeblocks: html-to-md-codeblocks.md 1`] = `
"Typescript is one of those languages that appear to be very simple. It's often described as \\"Javascript with types\\" and it fits that name very well. However, what many don't realize starting out with Typescript is that Typescript*is *a language and like all other languages it has it's own \\"secrets\\", it's own set of quirks.

When I started out with Typescript a few years back, I absolutely hated it. It was unnecessary, a box of clutter, making me write code that would never actually run. I hated defining interfaces, typing out all my functions, and thinking in terms I was not used to as a Javascript developer. Before Javascript, I had coded in C# and I had never really liked C# (I still don't) mostly for the huge amounts of boilerplate and magic involved. Typescript is heavily inspired by C# and seeing that contaminate the Javascript ecosystem irked me no end.

That was all just fluff. Typescript is a great language solving a considerable amount of problems for a huge amount of developers. And generics is the hidden weapon behind it all.

## Understanding Typescript generics

For all points and purposes, generics shouldn't exist. They are one of the main factors behind abysmal code readability. But in the right hands, generics turn into a super-weapon.

The main problem generics try to solve is how to take in multiple types of parameters. This is a solved problem but requires duplicating your functions or using conditions to separate out different logic for different types. That is essentially what generics do as well but hidden from human eyes.

Think of a container that can take any type of item as long as it is not a circle. In Javascript, this becomes a problem you have to solve at runtime with checks & conditions:

\`\`\`javascript
var container = [];
function putIntoContainer(item) {
    if (item.type === \\"round\\") throw new Error(\\"Rounded items not supported.\\")
    container.push(item);
}

var square = {type: \\"square\\"}
var circle = {type: \\"round\\"}
putIntoContainer(square)
putIntoContainer(circle) // ERROR! Rounded items not supported!
\`\`\`

There are many ways to solve this problem and some are even practical. The issue here isn't of repetition but of doing unnecessary work. Type safe languages would automatically give an error if there was a wrong type but Javascript knows nothing about the \`item\`.

In Typescript, this will be solved much more succinctly:

\`\`\`typescript
// first define the types of items we'll handle
// i.e. we don't want to handle any item other
// than square or round.
// This gives us nice auto completion and safety
// against typos.
type ItemTypes = \\"square\\" | \\"round\\";

// Define a generic item that can be of any type
// defined in ItemTypes.
// i.e. Item<\\"triangle\\"> will give an error.
type Item<TItemType extends ItemTypes> = {
 type?: TItemType;
 width: number;
 height: number;
};

// This is just syntax sugar to increase readability.
type Square = Item<\\"square\\">;
type Circle = Item<\\"round\\">;

// Our container is just a simple wrapper around an array
// that accepts items of only a specific type.
type Container<TItemType extends ItemTypes> = Array<Item<TItemType>>;

var squareContainer: Container<\\"square\\"> = [];
var roundContainer: Container<\\"round\\"> = [];

// This wrapper is unnecessary, of course, because array.push
// already does this. Only for demonstration purposes.
function putIntoContainer<
 TItemType extends ItemTypes,
 TItem extends Item<TItemType>
>(container: Container<TItemType>, item: TItem) {
 container.push(item);
}

var square: Square = { width: 100, height: 200 };
var circle: Circle = { width: 200, height: 500 };

putIntoContainer(squareContainer, square);
putIntoContainer(roundContainer, circle);
putIntoContainer(roundContainer, square); // Error: Argument of type 'Square' is not assignable to parameter of type 'Item<\\"round\\">'.
putIntoContainer(squareContainer, circle); // Error: Argument of type 'Circle' is not assignable to parameter of type 'Item<\\"square\\">'.
\`\`\`

A lot more code, I know, and if you don't know how generics work that blob of code is utter nonsense. One of the main reasons I avoided Typescript for a long time. But look at the benefits:

1. You have 100% compile-time type safety.

2. You can't put a round item in a square container (you will get compiler error).

3. You didn't write any extra runtime code.

Expanding on point #3, after transpilation the above code will turn more-or-less into:

\`\`\`javascript
var squareContainer = [];
var roundContainer = [];

function putIntoContainer(container, item) {
 container.push(item);
}

var square = { width: 100, height: 200 };
var circle = { width: 200, height: 500 };

putIntoContainer(squareContainer, square);
putIntoContainer(roundContainer, circle);
\`\`\`

This is the power of generics. More specifically, this is Typescript generics at a glance.

But this post was supposed to be about the \\"Secrets\\" of Typescript Generics, right? Well, let's get into that.

## 1\\\\. Type filters using ternary operators

## 2\\\\. Deeply recursive types

## 3\\\\. Type functions

## 4\\\\. Type inference using interface properties

"
`;

exports[`convert HTML to markdown with outlinelists: html-to-md-outlinelists.md 1`] = `
"Testing outline list:

- My outline list

- works

- but sometimes

    - It doesn't

    - what do I do?

    - I need to do something!

- Makes no sense!

- Yes it doesn't!

"
`;

exports[`convert HTML to markdown with tables: html-to-md-tables.md 1`] = `
"| Goal                                                                                                          | To introduce various features of the app to the user and to convert a user on trial or basic plan to upgrade. |
| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| Frequency                                                                                                     | 1/week or 2/week                                                                                              |
| Types                                                                                                         | Feature intro, upgrade promo, one time emails                                                                 |
|                                                                                                               |                                                                                                               |

## Emails

### Feature intro

Features:

1. Web clipper on mobile
2. Pin any note to notification
3. Take notes from notifications
4. App lock
5. Importer
6. Encrypted attachments
7. Session history & automatic backups
8. Note publishing
9. Note exports
10. Collapsible headers

### Promos

1. Trial about to end
2. Trial ending (with option to request an extension)
3. Try free for 14 days

### One time

1. End-of-month progress report
2. What's coming/roadmap
3. What we are working on
4. Join the community

"
`;

exports[`convert HTML to markdown with tables2: html-to-md-tables2.md 1`] = `
"# Note 8/6/22, 10:48 AM

hell

what

| sdsdavav       | daskvjbdsva    | vsadjkvsadbvjk |
| -------------- | -------------- | -------------- |
| dsvsajkdb      | dskajvbsadj    | kjdasvbkj      |
| daskvbkdsa     | kdsajvbsajkd   | kjdsavbdsa     |

"
`;

exports[`convert HTML to markdown with tasklists: html-to-md-tasklists.md 1`] = `
"Hello

- [x] Task item 1

- [x] Task item 2

- [x] Task item 3

- [ ] Task item 4

    - [ ] Sub task item 1

    - [ ] Sub task item 2

- [ ] Task Item 5

Nene

- dasvsadv

- adsva\\\\\`sd

- vasd

- vsadvdsa

"
`;
