Skip to content

Commit a82484d

Browse files
authored
Fix #1
except for 'mixed' type, needs more info
1 parent 24a3c0b commit a82484d

File tree

1 file changed

+155
-50
lines changed

1 file changed

+155
-50
lines changed

README.md

Lines changed: 155 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ I'm open to contributions and comments.
1818
| expressiveness | great (since TS @ 2.1) | great |
1919
| type safety | great (TS @ 2.0) | great |
2020
| typings for public libraries | plenty of well mainained typings | a handful of mostly incomplete typings |
21-
| unique features | autocomplete for object construction, huge library of mainained Typings, `readonly` properties, `never` type, namespacing | variance, existential types `*`, testing all potential code-paths when typings not declared for maximum inference, `$Diff<A, B>` type |
22-
| ecosystem flexibility | no extensions as of yet | no extensions as of yet |
21+
| unique features | <ul><li>autocomplete for object construction</li><li>declarable `this` in functions (typing binding)</li><li>large library of mainained typings</li><li>more flexible type mapping via iteration</li><li>namespacing</li></ul> | <ul><li>variance</li><li>existential types `*`</li><li>testing potential code-paths when types not declared for maximum inference</li><li>`$Diff<A, B>` type</li></ul> |
22+
| ecosystem flexibility | work in progress | no extensions |
23+
| programmatic hooking | architecture prepared, work in progress | work in progress |
2324

2425
# Differences in syntax
2526

@@ -122,28 +123,32 @@ declare module "*.css" {
122123

123124
## Exact/Partial Object Types
124125

125-
By default objects in Flow are not strict (exact), whereas in TypeScript they are always strict, unless set as partial.
126+
By default objects in Flow are not exact (can contain more properties than declared), whereas in TypeScript they are always exact (must contain only declared properties).
126127

127128
### Flow
128129

129130
When using flow, `{ name: string }` only means “an object with **at least** a name property”.
130131

131132
```js
132-
type StrictUser = {| name: string, age: number |};
133+
type ExactUser = {| name: string, age: number |};
133134
type User = { name: string, age: number };
134-
type PartialUser = $Shape<User>;
135+
type OptionalUser = $Shape<User>; // all properties become optional
135136
```
136137

137138
### TypeScript
138139

140+
TypeScript is more strict here, in that if you want to use a property which is not declared, you must explicitly say so by defining the indexed property. You will be allowed to use custom properties, but will have to access them through the bracket access syntax, i.e. UserInstance['someProperty']. At the moment, you cannot define "open" (non-exact) types using TypeScript. This is mostly a design decision as it forces you to write the typings upfront.
141+
139142
```js
140-
type StrictUser = { name: string, age: number };
141-
type PartialUser = Partial<{ name: string, age: number }>;
143+
type ExactUser = { name: string, age: number };
144+
type User = { name: string, age: number, [otherProperty: any] };
145+
type OptionalUser = Partial<{ name: string, age: number }>; // all properties become optional
142146
```
143147

144148
### Reference
145149

146150
- https://flowtype.org/docs/objects.html
151+
- https://github.com/Microsoft/TypeScript/issues/2710
147152

148153
## Importing types
149154

@@ -194,7 +199,10 @@ var props = {
194199
baz: 'three',
195200
}
196201

197-
function getProp<T>(key: $Enum<typeof props>): T {
202+
type PropsType = typeof props;
203+
type KeysOfProps = $Enum<PropsType>;
204+
205+
function getProp<T>(key: KeysOfProps): T {
198206
return props[key]
199207
}
200208
```
@@ -209,92 +217,171 @@ var props = {
209217
}
210218

211219
type PropsType = typeof props
220+
type KeysOfProps = keyof PropsType;
212221

213-
function getProp<K extends keyof PropsType>(key: K): PropsType[K] {
222+
function getProp<T>(key: KeysOfProps): T {
214223
return props[key]
215224
}
216225
```
217226

218-
## Mapped Types
219-
220-
TODO: use an example which does the same
227+
## Records
221228

222229
### Flow
223230

224231
```js
225-
type ExtractCodomain = <V>(v: () => V) => V;
226-
function f<O>(o: O): $ObjMap<O, ExtractCodomain>;
232+
type $Record<T, U> = {[key: $Enum<T>]: U}
233+
type SomeRecord = $Record<{ a: number }, string>
227234
```
228235

229236
### TypeScript
230237

231238
```ts
232-
type Partial<T> = {
233-
[P in keyof T]?: T[P];
234-
};
239+
type SomeRecord = Record<{ a: number }, string>
235240
```
236241
237-
# Same syntax
242+
## Lookup Types
238243
239-
Most of the syntax of Flow and TypeScript is the same. TypeScript is more expressive for certain use-cases (advanced mapped types with keysof, readonly properties), and Flow is more expressive for others (e.g. `$Diff`).
244+
### Flow
240245
241-
## optional parameters
246+
```js
247+
type A = {
248+
thing: string
249+
}
242250

243-
### Flow and TypeScript
251+
type lookedUpThing = $PropertyType<A, 'thing'>
252+
```
244253
245-
```js
246-
function(a?: string) {}
254+
### TypeScript
255+
256+
```ts
257+
type A = {
258+
thing: string
259+
}
260+
261+
type lookedUpThing = typeof A['thing']
247262
```
248263
249-
## Flow's "mixed" type
264+
## Mapped Types / Foreach Property
250265
251-
Flow's `mixed` type is simply a union of all the basic types (string, number, boolean) without their Object versions.
266+
### Flow
267+
268+
```js
269+
type InputType = { hello: string };
270+
type MappedType = $ObjMap<InputType, number>;
271+
```
272+
273+
### TypeScript
252274

253-
The TypeScript equivalent should be:
275+
A bit more flexibility here, as you have access to each individual key name and can combine with Lookup types and even do simple transformations.
254276

255277
```ts
256-
type mixed = string | number | boolean
278+
type InputType = { hello: string };
279+
type MappedType = {
280+
[P in keyof InputType]: number;
281+
};
257282
```
258283

259-
Reference: https://flowtype.org/docs/quick-reference.html#mixed
284+
## Read-only Types
260285

261-
# TypeScript-only concepts
286+
### Flow
262287

263-
## [Non-null assertion operator](https://github.com/Microsoft/TypeScript/pull/7140)
288+
```js
289+
type A = {
290+
+b: string
291+
}
264292

265-
Add `!` to signify we know an object is non-null.
293+
let a: A = { b: 'something' }
294+
a.b = 'something-else'; // ERROR
295+
a = { b: 'something-else' } // ERROR: reassignment is NOT allowed in Flow
296+
```
297+
298+
### TypeScript
266299

267300
```ts
268-
// Compiled with --strictNullChecks
269-
function validateEntity(e: Entity?) {
270-
// Throw exception if e is null or invalid entity
301+
type A = {
302+
readonly b: string
271303
}
272304

273-
function processEntity(e: Entity?) {
274-
validateEntity(e);
275-
let s = e!.name; // Assert that e is non-null and access name
305+
let a: A = { b: 'something' }
306+
a.b = 'something-else'; // ERROR
307+
a = { b: 'something-else' } // OK: reassignment is alowed in TypeScript
308+
```
309+
310+
## "Impossible flow" type
311+
312+
### Flow
313+
314+
`empty`
315+
316+
```js
317+
function returnsImpossible() {
318+
throw new Error();
276319
}
320+
321+
// type of returnsImpossible() is 'empty'
277322
```
278323

279-
## Lookup Types
324+
### TypeScript
325+
326+
`never`
280327

281328
```ts
282-
type A = {
283-
thing: string
329+
function returnsImpossible() {
330+
throw new Error();
284331
}
285332

286-
type lookedUpThing = typeof A['thing']
333+
// type of returnsImpossible() is 'never'
287334
```
288335

289-
## Read-only Types
336+
# Same syntax
337+
338+
Most of the syntax of Flow and TypeScript is the same. TypeScript is more expressive for certain use-cases (advanced mapped types with keysof, readonly properties), and Flow is more expressive for others (e.g. `$Diff`).
339+
340+
## optional parameters
341+
342+
### Flow and TypeScript
343+
344+
```js
345+
function(a?: string) {}
346+
```
347+
348+
# TypeScript-only concepts
349+
350+
## Declarable arbitrary `this` in functions (outside of objects)
290351

291352
```ts
292-
type A = {
293-
readonly b: string
353+
function something(this: { hello: string }, firstArg: string) {
354+
return this.hello + firstArg;
294355
}
356+
```
295357

296-
let a: A = { b: 'something' }
297-
a.b = 'something-else'; // ERROR
358+
## Private and Public properties in classes
359+
360+
```ts
361+
class SomeClass {
362+
constructor(public prop: string, private prop2: string) {
363+
// transpiles to:
364+
// this.prop = prop;
365+
// this.prop2 = prop2;
366+
}
367+
private prop3: string;
368+
}
369+
```
370+
371+
## [Non-null assertion operator](https://github.com/Microsoft/TypeScript/pull/7140)
372+
373+
Add `!` to signify we know an object is non-null.
374+
375+
```ts
376+
// Compiled with --strictNullChecks
377+
function validateEntity(e: Entity?) {
378+
// Throw exception if e is null or invalid entity
379+
}
380+
381+
function processEntity(e: Entity?) {
382+
validateEntity(e);
383+
let s = e!.name; // Assert that e is non-null and access name
384+
}
298385
```
299386

300387
# Flow-only concepts
@@ -306,17 +393,21 @@ type C = $Diff<{ a: string, b: number }, { a: string }>
306393
// C is { b: number}
307394
```
308395

309-
TypeScript has a proposal for this (needs link).
396+
TypeScript has a [proposal](https://github.com/Microsoft/TypeScript/issues/12215) for an equivalent.
397+
398+
## `$Subtype<T>`
310399

311-
## Inferred generics / existential types
400+
In TypeScript, structural types are always subtypes of themselves, so there is no need for such a concept.
312401

313-
`*` as a generic parameter tries to infer the type if possible
402+
## Inferred existential types
403+
404+
`*` as a type or a generic parameter signifies to the type-checker to infer the type if possible
314405

315406
```js
316407
Array<*>
317408
```
318409

319-
TypeScript has a proposal for this (needs link).
410+
TypeScript has a proposal for an equivalent (needs link).
320411

321412
## Variance
322413

@@ -330,6 +421,20 @@ function getLength(o: {+p: ?string}): number {
330421
331422
[TypeScript proposal](https://github.com/Microsoft/TypeScript/issues/10717)
332423
424+
## Flow's "mixed" type
425+
426+
NOTE: This is probably incorrect (#1). Open to PRs with corrections.
427+
428+
Flow's `mixed` type is simply a union of all the basic types (string, number, boolean) without their Object versions.
429+
430+
The TypeScript polyfill/equivalent should be:
431+
432+
```ts
433+
type mixed = string | number | boolean
434+
```
435+
436+
Reference: https://flowtype.org/docs/quick-reference.html#mixed
437+
333438
## Useful References
334439
335440
* https://github.com/Microsoft/TypeScript/issues/1265

0 commit comments

Comments
 (0)