-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
35 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,80 +1,59 @@ | ||
# null-safety | ||
## null-safety | ||
|
||
[![CircleCI](https://circleci.com/gh/ponponner/null-safety.svg?style=svg)](https://circleci.com/gh/ponponner/null-safety) | ||
|
||
プロパティへの`null-safety`かつ`undefined-safety`かつ型安全かつ連続的な参照をサポートするクラス(を目指したもの)です。 | ||
## example: | ||
|
||
### 利用例: | ||
```ts:demo.ts | ||
const html = ` | ||
<html> | ||
<h1>this is a title</h1> | ||
</html> | ||
`; | ||
|
||
例えば次の図のように、関数`querySelector`を利用したその結果は`null`や`undefined`かもしれません。 | ||
それをチェックすると流れを崩しますし、気にせずずずずずと書きたい時があります。 | ||
const doc = new JSDOM(html).window.document; | ||
|
||
そこで関数`next`を利用します。これにより、次の関数`next`において`null`や`undefined`を考慮した冗長なコードを記述する必要がなくなります。 その一方で、代替の値を設定することもできます。 | ||
![image](./docs/img/demo0.png) | ||
const title = NullSafety.start(doc) | ||
.next(o => o.querySelector('h1')) | ||
.next(o => o.textContent) | ||
.resultAlty('title-for-failed'); | ||
|
||
詳しくは、定義をご参照下さい。 | ||
console.log(title); | ||
// output: this is a title | ||
``` | ||
|
||
### 型安全: | ||
## type-safety: | ||
|
||
関数`next`には、次の値取得用の関数を渡し次の値の取得を任せます。利用例で見たように、次の値を取得した結果は`null`や`undefined`でありえることがあります。 | ||
![image](./docs/img/demo1.png) | ||
```ts | ||
const title = NullSafety.start(doc) | ||
|
||
次の関数`next`では、前の値が`null`や`undefined`であった場合には、次の値取得用の関数を実行せずそのまま元の値を次の値とします。これにより、次の図のように関数`next`へ渡す関数の引数を`null`でない型のみとでき、TypeScriptにおいて有用です。 | ||
![image](./docs/img/demo2.png) | ||
.next(o => o.querySelector('h1')) | ||
// return: HTMLHeadingElement | null | ||
|
||
.next(o => o.textContent) | ||
// argument: HTMLHeadingElement (not nullable *>_<)b! | ||
// return: string | null | ||
|
||
.resultAlty('title-for-failed'); | ||
// return: string (not nullable *>_<)b! | ||
``` | ||
|
||
## 要件 | ||
## recommendation: | ||
|
||
TypeScript のコンパラーオプションにおいて、`strictNullChecks`または`strict`を有効にする必要があります(`strict`は`strictNullChecks`を有効にします)。 | ||
Use TypeScript & TypeScript compiler option: `strictNullChecks`(or `strict`) | ||
|
||
```json:tsconfig.json | ||
{ | ||
"compilerOptions": { | ||
"strict": true, | ||
"strictNullChecks": true, | ||
... | ||
}, | ||
... | ||
} | ||
} | ||
``` | ||
|
||
## その他の例 | ||
// or | ||
|
||
```ts | ||
import NullSafety from './null-safety'; | ||
import { JSDOM } from 'jsdom'; | ||
|
||
const htmlA = ` | ||
<html> | ||
<h1>this is page A</h1> | ||
</html> | ||
`; | ||
const htmlB = ` | ||
<html> | ||
<h3>this is page B</h3> | ||
</html> | ||
`; | ||
|
||
interface ITextFetched { | ||
isSucceeded: boolean; | ||
text: string; | ||
{ | ||
"compilerOptions": { | ||
"strict": true, | ||
} | ||
} | ||
|
||
const fetchTitle = (html: string): ITextFetched => { | ||
const doc = new JSDOM(html).window.document; | ||
const title = NullSafety.start(doc) | ||
.next(o => o.querySelector('h1')) | ||
.next(o => o.textContent); | ||
return { | ||
isSucceeded: title.result() != null, | ||
text: title.resultAlty('title-unfetched'), | ||
}; | ||
}; | ||
|
||
console.log(`title of pageA: ${fetchTitle(htmlA).text}`); | ||
// title of pageA: this is page A | ||
|
||
console.log(`title of pageB: ${fetchTitle(htmlB).text}`); | ||
// title of pageB: title-unfetched | ||
``` |
Binary file not shown.
Binary file not shown.
Binary file not shown.