-
Notifications
You must be signed in to change notification settings - Fork 0
/
rss2.xml
207 lines (125 loc) · 160 KB
/
rss2.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>Ike's blog</title>
<link>https://qiyanan.com/</link>
<atom:link href="/rss2.xml" rel="self" type="application/rss+xml"/>
<description></description>
<pubDate>Fri, 26 Jun 2020 02:47:03 GMT</pubDate>
<generator>http://hexo.io/</generator>
<item>
<title>React-redux</title>
<link>https://qiyanan.com/2020/05/14/React-redux/</link>
<guid>https://qiyanan.com/2020/05/14/React-redux/</guid>
<pubDate>Thu, 14 May 2020 02:07:40 GMT</pubDate>
<description>
<h1 id="redux基础"><a href="#redux基础" class="headerlink" title="redux基础"></a>redux基础</h1><h2 id="store"><a href="#store" class="headerlink" ti
</description>
<content:encoded><![CDATA[<h1 id="redux基础"><a href="#redux基础" class="headerlink" title="redux基础"></a>redux基础</h1><h2 id="store"><a href="#store" class="headerlink" title="store"></a>store</h2><p>是保存数据的地方。可以把它看成一个容器,整个应用只能有一个 Store。<br>Redux 提供 createStore 这个函数,用来生成 Store。 </p><p><code>import {createStore} from 'redux';</code></p><p><code>const store = createStore(reducer);</code></p><p>store.getState() </p><p>store 对象包含所有的数据,如果想得到某个时点的数据,就要对 Store 生成快照,这种时点的数据集合,就叫做 State, 当前时刻的 State,可以通过 store.getState() 拿到。</p><p>store.dispatch() 是 View 发出 Action 的唯一方法。结合 Action Creator store.dispatch(addTodo(“Learn Redux”)); </p><p>store.subscribe(listener) 监听函数,一旦 State 发生变化,就会自动执行这个函数。在 React 项目中,就是把组件的 render 方法或 setState 方法放入 Listen,就会实现 View 的自动渲染了</p><h2 id="action"><a href="#action" class="headerlink" title="action"></a>action</h2><p>action 是一个对象,有一个必选 type 属性,其他属性自选: 作用是把 View 传进来的 state 改变之后返回一个新的 state</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">const action = {</span><br><span class="line"> type: 'Add-Todo',</span><br><span class="line"> payload: 'learn more'</span><br><span class="line">}</span><br><span class="line">``` </span><br><span class="line">如果 View 要发生很多种类的消息,就会产生很多种 action,因此,我们可以定义一个函数来生成 Action,这个函数叫做 Action Creator。</span><br><span class="line"></span><br><span class="line">``` </span><br><span class="line">const ADD_TODO = '添加 TODO';</span><br><span class="line">function addTodo(text){</span><br><span class="line"> return {</span><br><span class="line"> type: ADD_TODO,</span><br><span class="line"> text</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line">const action = addTodo('Learn Redux');</span><br></pre></td></tr></table></figure><h2 id="reducer"><a href="#reducer" class="headerlink" title="reducer"></a>reducer</h2><p>Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生改变。这种 State 的计算过程叫做 Reducer<br>是一个函数,接收 Action 和一个当前 State 作为参数,返回一个新的 State。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">const reducer = (state, action) => {</span><br><span class="line"> switch (action.type) {</span><br><span class="line"> case '400':</span><br><span class="line"> return state = action.payload;</span><br><span class="line"> default:</span><br><span class="line"> return state;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">``` </span><br><span class="line"></span><br><span class="line">reducer 函数的最重要特征是, 他是一个纯函数,也就是说,只要是同样的输入,必定得到同样的输出。</span><br><span class="line">纯函数是函数式编程的概念,必须遵守以下一些约束:</span><br><span class="line"></span><br><span class="line">1. 不得改写参数</span><br><span class="line">2. 不能调用系统 I/O 的 API</span><br><span class="line">3. 不能调用 Date.now() 或者 Math.random() 等不纯的方法,因为每次会得倒不一样的结果。</span><br><span class="line"></span><br><span class="line">由于 Reducer 是纯函数,就可以保证同样的 State,必定得到同样的 View, 但也正因为这一点,Reducer 函数里面不能改变 State,必须返回一个全新的对象,请参考下面的写法。</span><br><span class="line"></span><br><span class="line">``` </span><br><span class="line">// state 是一个对象</span><br><span class="line">function reducer (state, action){</span><br><span class="line"> return Object.assign({}, state, {thingToChange});</span><br><span class="line"> // 或者</span><br><span class="line"> return {...state, ...newState };</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// state 是一个数组</span><br><span class="line">function reducer(state, action){</span><br><span class="line"> return {...state, newItem};</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="中间件(middleware)"><a href="#中间件(middleware)" class="headerlink" title="中间件(middleware)"></a>中间件(middleware)</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">import {applyMiddleware, createStore} from 'redux';</span><br><span class="line">import createLogger from 'redux-logger';</span><br><span class="line">const logger = createLogger();</span><br><span class="line">const store = createStore(reducer, applyMiddleware(logger));</span><br><span class="line">const store = createStore(reducer, applyMiddleware(thunk, promise, logger))</span><br></pre></td></tr></table></figure><p>上面代码中,applyMiddleware 方法的三个参数,就是三个中间件,有的中间件有次序要求,比如,logger 一定放在最后,否则输出结果就会不正确。</p><h1 id="React-Redux:"><a href="#React-Redux:" class="headerlink" title="React-Redux:"></a>React-Redux:</h1><p>React-Redux 将所有的组件分为两大类:UI 组件和容器组件<br>UI 组件负责 UI 的呈现,容器组件负责管理数据和逻辑。<br>React-Redux 提供 connect 方法,用于从 UI 组件生成容器组件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">import { connect } from 'react-redux'</span><br><span class="line">const VisibleTodoList = connect()(TodoList);</span><br></pre></td></tr></table></figure><p>上面代码中, TodoList 是 UI 组件,VisTodoList 就是由 React-Redux 自动生成的容器组件。但是,因为没有定义业务逻辑,丧母暗的这个容器的组件毫无意义,只是UI的一个单纯的包装层,为了定义业务逻辑,需要给出下面来那个方面的信息</p><ol><li>输入逻辑: 外部的数据(即 state 对象)如何转换为 UI 组件的参数。</li><li>输出逻辑: 用户的动作如何变为 Action 对象,从 UI 组件传出去。</li></ol><p>因此,connect 方法的完整 API 如下,</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">import {connect} from 'react-redux'</span><br><span class="line">const VisibleTodoList = connect(</span><br><span class="line"> mapStateToProps,</span><br><span class="line"> mapDispatchToProps</span><br><span class="line">)(TodoList)</span><br></pre></td></tr></table></figure><p>上面代码中,connect 方法接受两个参数:mapStateToProps 和 mapDispatchToProp, 他们定义了 UI 组件的业务逻辑,前者负责输入逻辑,后者负责输出逻辑。即将 state 映射到 UI 组件的参数 (props), 后者负责输出逻辑,即将用户对 UI 组件的操作映射成 Action.</p><h2 id="mapStateToProps"><a href="#mapStateToProps" class="headerlink" title="mapStateToProps()"></a>mapStateToProps()</h2><p>mapStateToProps 是一个函数,作用是建立一个(外部的)state 对象到(UI组件的)props 对象的映射关系。<br>作为函数,mapStateToProps执行后应该返回一个对象,里面的每一个键值对就是一个映射。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">const mapStateToProps = (state) => {</span><br><span class="line"> return {</span><br><span class="line"> todos: getVisibleTodos(state.todos, state.visibilityFilter)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>上面代码中,mapStateToProps 是一个函数,它接受 state 作为参数,返回一个对象,这个对象有一个 todos 属性,代表 UI 组件的同名参数,后面的 getVisibleTodos 也是一个函数,可以从 state 算出 todos 的值。<br>下面就是 getVisibleTodos 的一个例子,用来算出 todos。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">const getVisibleTodos = (todos, filter) => {</span><br><span class="line"> switch (filter){</span><br><span class="line"> case 'SHOW_ALL':</span><br><span class="line"> return todos</span><br><span class="line"> case 'SHOW_COMPLETED':</span><br><span class="line"> return todos.filter(t => t.completed)</span><br><span class="line"> case 'SHOW_ACTIVE':</span><br><span class="line"> return todos.filter(t => !t.completed)</span><br><span class="line"> default</span><br><span class="line"> throw new Error('Unknown filter:' + filter)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>mapStateToProps 会订阅 Store, 每当 state 更新的时候,就会自动执行,重新计算 UI 组件的参数,从而触发 UI 组件的重新渲染。<br>mapStateToProps 的第一个参数总是 state 对象,还可以使用第二个参数,代表容器组件的 props 对象。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">const mapStateToProps = (state, ownProps) => {</span><br><span class="line"> return {</span><br><span class="line"> active: ownProps.filter ===state.VisibilityFilter</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>使用 ownProps作为参数后,如果容器组件的参数发生变化,也会引发 UI 组件重新渲染。<br>connect 方法可以省略 mapStateToProps 参数,那样的话,UI组件就不会订阅 Store, 就是说 Store 的更新不会引起 UI 组件的更新。</p><h2 id="mapDispatchToProps"><a href="#mapDispatchToProps" class="headerlink" title="mapDispatchToProps()"></a>mapDispatchToProps()</h2><p>mapDispatchProps 是 connect 函数的第二个参数,用来建立 UI 组件的参数到 Store.dispatch方法的映射,也就是说。它定义了哪些用户的操作应该当作Action, 它可以是一个函数,也可以是一个对象。<br>如果mapDispatchProps是一个函数,会得倒 dispatch 和 ownProps (容器组件的props对象)两个参数。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">const mapDispatchToProps = (dispatch, ownProps) => {</span><br><span class="line"> return {</span><br><span class="line"> onClick: () => {</span><br><span class="line"> dispatch({</span><br><span class="line"> type: 'SET_VISIBILITY_FILTER',</span><br><span class="line"> filter: ownProps.filter</span><br><span class="line"> })</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>如果 mapDispatchToProps 是一个对象, 它的每个键名也是对应 UI 组件的同名参数,会被当作 Action creator,返回的 Action 会由 Redux 自动发出</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">const mapDispatchToProps = {</span><br><span class="line"> onclick: (filter) => {</span><br><span class="line"> type: 'SET_VISIBILITY_FILTER',</span><br><span class="line"> filter: filter</span><br><span class="line"> };</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="组件"><a href="#组件" class="headerlink" title=" 组件"></a><provider> 组件</provider></h2><p>connect 方法生成容器组件以后,需要让容器组件拿到 state 对象。才能生成 UI 组件的参数。<br>React-Redux 提供 Provider 组件,可以让容器组件拿到 state。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">import { Provider} from 'react-redux'</span><br><span class="line">import { createStore } from 'redux'</span><br><span class="line">import todoApp from './reducers'</span><br><span class="line">import App from './components/App'</span><br><span class="line"></span><br><span class="line">let store = createStore(todoApp);</span><br><span class="line"></span><br><span class="line">render(</span><br><span class="line"> <Provider store = {store}></span><br><span class="line"> <App /></span><br><span class="line"> </Provider>,</span><br><span class="line"> document.getElementById('root')</span><br><span class="line">)</span><br></pre></td></tr></table></figure><p>上面代码中,Provider在根组件外面包了一层,这样一来,App 的所有制组件就默认拿到 state了。</p>]]></content:encoded>
<comments>https://qiyanan.com/2020/05/14/React-redux/#disqus_thread</comments>
</item>
<item>
<title>Cypress-常用函数</title>
<link>https://qiyanan.com/2019/09/13/Cypress-%E5%B8%B8%E7%94%A8%E5%87%BD%E6%95%B0/</link>
<guid>https://qiyanan.com/2019/09/13/Cypress-%E5%B8%B8%E7%94%A8%E5%87%BD%E6%95%B0/</guid>
<pubDate>Fri, 13 Sep 2019 06:28:39 GMT</pubDate>
<description>
<h1 id="Cypress"><a href="#Cypress" class="headerlink" title="Cypress"></a>Cypress</h1><h2 id="prev-获取当前元素的上一个兄弟元素"><a href="#prev-获取当前元素的上一
</description>
<content:encoded><![CDATA[<h1 id="Cypress"><a href="#Cypress" class="headerlink" title="Cypress"></a>Cypress</h1><h2 id="prev-获取当前元素的上一个兄弟元素"><a href="#prev-获取当前元素的上一个兄弟元素" class="headerlink" title="prev() 获取当前元素的上一个兄弟元素"></a>prev() 获取当前元素的上一个兄弟元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cy.get('.action-focus').focus()</span><br><span class="line"> .should('have.class', 'focus')</span><br><span class="line"> .prev().should('have.attr', 'style', 'color: orange;')</span><br></pre></td></tr></table></figure><h2 id="submit-The-subject-must-be-a-form"><a href="#submit-The-subject-must-be-a-form" class="headerlink" title="submit() The subject must be a form"></a>submit() The subject must be a form</h2><p><code>cy.get('form').submit()</code></p><h2 id="next-获取当前元素的下一个兄弟元素"><a href="#next-获取当前元素的下一个兄弟元素" class="headerlink" title="next() 获取当前元素的下一个兄弟元素"></a>next() 获取当前元素的下一个兄弟元素</h2><h2 id="click-单击一个元素"><a href="#click-单击一个元素" class="headerlink" title="click() 单击一个元素"></a>click() 单击一个元素</h2><ol><li>我们可以点击一个元素的9个特殊的位置</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"> -----------------------------------</span><br><span class="line">| topLeft top topRight |</span><br><span class="line">| |</span><br><span class="line">| |</span><br><span class="line">| |</span><br><span class="line">| left center right |</span><br><span class="line">| |</span><br><span class="line">| |</span><br><span class="line">| |</span><br><span class="line">| bottomLeft bottom bottomRight |</span><br><span class="line"> -----------------------------------</span><br></pre></td></tr></table></figure><ol start="2"><li>我们可以接受一个 x 和 y 坐标</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">cy.get('#action-canvas')</span><br><span class="line"> .click(80, 75) // click 80px on x coord and 75px on y coord</span><br><span class="line"> .click(170, 75)</span><br><span class="line"> .click(80, 165)</span><br><span class="line"> .click(100, 185)</span><br><span class="line"> .click(125, 190)</span><br><span class="line"> .click(150, 185)</span><br><span class="line"> .click(170, 165)</span><br></pre></td></tr></table></figure><ol start="3"><li>可以通过 multiple: true 点击多个元素</li></ol><p><code>cy.get('.action-labels>.label').click({ multiple: true })</code></p><h2 id="dbclick-双击一个元素"><a href="#dbclick-双击一个元素" class="headerlink" title="dbclick() 双击一个元素"></a>dbclick() 双击一个元素</h2><p><code>cy.get('.action-div').dblclick().should('not.be.visible')</code></p><h2 id="check-选中复选框或者单选框,并且可以接收单选或复选按钮的-value-参数"><a href="#check-选中复选框或者单选框,并且可以接收单选或复选按钮的-value-参数" class="headerlink" title="check() 选中复选框或者单选框,并且可以接收单选或复选按钮的 value 参数"></a>check() 选中复选框或者单选框,并且可以接收单选或复选按钮的 value 参数</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">cy.get('.action-multiple-checkboxes [type="checkbox"]')</span><br><span class="line"> .check(['checkbox1', 'checkbox2']).should('be.checked')</span><br><span class="line">cy.get('.action-radios [type="radio"]')</span><br><span class="line"> .check('radio1').should('be.checked')</span><br></pre></td></tr></table></figure><h2 id="uncheck-默认情况下,uncheck-将取消所有匹配,也可接收一个-value-参数"><a href="#uncheck-默认情况下,uncheck-将取消所有匹配,也可接收一个-value-参数" class="headerlink" title="uncheck() 默认情况下,uncheck() 将取消所有匹配,也可接收一个 value 参数"></a>uncheck() 默认情况下,uncheck() 将取消所有匹配,也可接收一个 value 参数</h2><p><code>cy.get('.action-check [type="checkbox"]').check('checkbox1').uncheck('checkbox1').should('not.be.checked')</code></p><h2 id="select-选择一个选项在下拉菜单的元素里,select-使用文本匹配,也可使用-value-匹配"><a href="#select-选择一个选项在下拉菜单的元素里,select-使用文本匹配,也可使用-value-匹配" class="headerlink" title="select() 选择一个选项在下拉菜单的元素里,select() 使用文本匹配,也可使用 value 匹配"></a>select() 选择一个选项在下拉菜单的元素里,select() 使用文本匹配,也可使用 value 匹配</h2><p><code>cy.get('.action-select-multiple') .select(['apples', 'oranges', 'bananas'])</code></p><p><code>cy.get('.action-select-multiple') .select(['fr-apples', 'fr-oranges', 'fr-bananas'])</code></p><h2 id="scrollIntoVIew-将一个元素滚动到视图中,Cypress-知道向右和向下滚动"><a href="#scrollIntoVIew-将一个元素滚动到视图中,Cypress-知道向右和向下滚动" class="headerlink" title="scrollIntoVIew() 将一个元素滚动到视图中,Cypress 知道向右和向下滚动"></a>scrollIntoVIew() 将一个元素滚动到视图中,Cypress 知道向右和向下滚动</h2><p><code>cy.get('#scroll-both button').scrollIntoView().should('be.visible')</code></p><h2 id="scrollTO-可以将窗口或者一个可滚动元素拖到一个明确的位置"><a href="#scrollTO-可以将窗口或者一个可滚动元素拖到一个明确的位置" class="headerlink" title="scrollTO() 可以将窗口或者一个可滚动元素拖到一个明确的位置"></a>scrollTO() 可以将窗口或者一个可滚动元素拖到一个明确的位置</h2><p><code>cy.scrollTo('bottom') // 如果直接和cy链式调用,将直接滚动整个窗口</code></p><p><code>cy.get('#scrollable-vertical').scrollTo(250, 250) // 滚动到一个明确的位置</code></p><p><code>cy.get('#scrollable-vertical').scrollTo('center', { easing: 'linear' }) // 控制滚动的缓动</code></p><h2 id="trigger-触发一个Dom元素的事件"><a href="#trigger-触发一个Dom元素的事件" class="headerlink" title="trigger() 触发一个Dom元素的事件"></a>trigger() 触发一个Dom元素的事件</h2><h2 id="its-获取前一个返回值的属性值"><a href="#its-获取前一个返回值的属性值" class="headerlink" title="its 获取前一个返回值的属性值"></a>its 获取前一个返回值的属性值</h2><h2 id="invoke-在前面生成的主题上调用方法"><a href="#invoke-在前面生成的主题上调用方法" class="headerlink" title="invoke() 在前面生成的主题上调用方法"></a>invoke() 在前面生成的主题上调用方法</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">cy.get('.trigger-input-range')</span><br><span class="line"> .invoke('val', 25)</span><br><span class="line"> .trigger('change')</span><br><span class="line"> .get('input[type=range]').siblings('p')</span><br><span class="line"> .should('have.text', '25');</span><br></pre></td></tr></table></figure><h2 id="as-可以给一个路由或者-DOM-元素起别名"><a href="#as-可以给一个路由或者-DOM-元素起别名" class="headerlink" title="as() 可以给一个路由或者 DOM 元素起别名"></a>as() 可以给一个路由或者 DOM 元素起别名</h2><h2 id="first-获取一组-DOM-元素的第一个元素"><a href="#first-获取一组-DOM-元素的第一个元素" class="headerlink" title="first() 获取一组 DOM 元素的第一个元素"></a>first() 获取一组 DOM 元素的第一个元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">cy.get('.as-table')</span><br><span class="line"> .find('tbody>tr').first()</span><br><span class="line"> .find('td').first()</span><br><span class="line"> .find('button').as('firstBtn');</span><br><span class="line"> </span><br><span class="line">// 在别名前面加上 @ </span><br><span class="line">cy.get('@firstBtn').click();</span><br></pre></td></tr></table></figure><h2 id="server-打开一个服务器,将responses-路由到-cy-route-和-cy-request"><a href="#server-打开一个服务器,将responses-路由到-cy-route-和-cy-request" class="headerlink" title="server() 打开一个服务器,将responses 路由到 cy.route() 和 cy.request()."></a>server() 打开一个服务器,将responses 路由到 cy.route() 和 cy.request().</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cy.server();</span><br><span class="line">cy.route('GET', 'comments/*').as('getComment')</span><br></pre></td></tr></table></figure><h2 id="should-对当前的主题做一个断言"><a href="#should-对当前的主题做一个断言" class="headerlink" title="should() 对当前的主题做一个断言"></a>should() 对当前的主题做一个断言</h2><p>判断当前主题的类名是success</p><p><code>should('have.class', 'success')</code></p><p>多种方式检查文本元素</p><p><code>should('have.text', 'Colum content')</code></p><p><code>should('contain', 'Colum content')</code></p><p><code>should('have.html', 'Colum content')</code></p><p>检查元素是否获取到</p><p><code>should('match', 'td')</code></p><p>使用正则表达式进行文本内容匹配</p><p><code>.invoke('text').should('match', /colum content/i)</code></p><p><strong><em>cy.contains</em></strong> <strong>是一个更好的使用正则表达式匹配文本内容的方法</strong></p><p><code>cy.get('.assertion-table').find('tbody tr:last') .contains('td', /column content/i).should('be.visible')</code></p><h2 id="should-对当前的主题做一个断言-1"><a href="#should-对当前的主题做一个断言-1" class="headerlink" title="should() 对当前的主题做一个断言"></a>should() 对当前的主题做一个断言</h2><p>判断当前主题的类名是success</p><p><code>should('have.class', 'success')</code></p><p>多种方式检查文本元素</p><p><code>should('have.text', 'Colum content')</code></p><p><code>should('contain', 'Colum content')</code></p><p><code>should('have.html', 'Colum content')</code></p><p>检查元素是否获取到</p><p><code>should('match', 'td')</code></p><p>使用正则表达式进行文本内容匹配</p><p><code>.invoke('text').should('match', /colum content/i)</code></p><p><strong><em>cy.contains()</em></strong> <strong>是一个更好的使用正则表达式匹配文本内容的方法</strong></p><p><code>cy.get('.assertion-table').find('tbody tr:last') .contains('td', /column content/i).should('be.visible')</code></p><h2 id="and-将多个断言链接在一起"><a href="#and-将多个断言链接在一起" class="headerlink" title=".and() 将多个断言链接在一起"></a>.and() 将多个断言链接在一起</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">cy.get('.assertions-link')</span><br><span class="line"> .should('have.class', 'active')</span><br><span class="line"> .and('have.attr', 'href')</span><br><span class="line"> .and('include', 'cypress.io')</span><br></pre></td></tr></table></figure><h2 id="expect"><a href="#expect" class="headerlink" title="expect"></a>expect</h2><p>对指定的主题做 BDD 断言,使用expect</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">describe('Explicit Assertions', () => {</span><br><span class="line"> it("expect - make an assertion about a specified subject", () => {</span><br><span class="line"> expect(true).to.be.true;</span><br><span class="line"> const o = { foo: 'bar' };</span><br><span class="line"> expect(o).to.equal(o);</span><br><span class="line"> expect(o).to.deep.equal({ foo: 'bar' });</span><br><span class="line"> expect('FooBar').to.match(/bar$/i);</span><br><span class="line"> });</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h2 id="assert"><a href="#assert" class="headerlink" title="assert"></a>assert</h2><p>对指定的主题进行TDD 断言,使用 assert</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">it("assert - assert shape of an object", () => {</span><br><span class="line"> const person={</span><br><span class="line"> name:'Joe',</span><br><span class="line"> age:20,</span><br><span class="line"> }</span><br><span class="line"> assert.isObject(person,'value is object');</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h2 id="带有回调函数的-should"><a href="#带有回调函数的-should" class="headerlink" title="带有回调函数的 should"></a>带有回调函数的 should</h2><p>如果包含的断言不够,我们可以使用 .should(cb) 函数写我们自己复杂的检查,将包含任意数量的显式断言的函数,传递给 should(), 回调函数将会被重试直到通过你的显示断言或者超时</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">it('pass your own callback function to should()', () => {</span><br><span class="line"> cy.get('.assertions-p')</span><br><span class="line"> .find('p')</span><br><span class="line"> .should(($p) => {</span><br><span class="line"> const texts = $p.map((i, el) => Cypress.$(el).text());</span><br><span class="line"> const paragraphs = texts.get();</span><br><span class="line"> expect(paragraphs, 'has 3 paragraphs').to.have.length(3);</span><br><span class="line"> expect(paragraphs, 'has expected text in each paragraph').to.deep.eq([</span><br><span class="line"> 'Some text from first p',</span><br><span class="line"> 'More text from second p',</span><br><span class="line"> 'And even more text from third p',</span><br><span class="line"> ]);</span><br><span class="line"> });</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h2 id="each-遍历一个元素数组"><a href="#each-遍历一个元素数组" class="headerlink" title="each() 遍历一个元素数组"></a>each() 遍历一个元素数组</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">it('.each() - iterate over an array of elements', () => {</span><br><span class="line"> cy.get('.connectors-each-ul>li')</span><br><span class="line"> .each(($el, index, $list) => {</span><br><span class="line"> console.log($el, index, $list);</span><br><span class="line"> });</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h2 id="spread-将一个数组作为一个单独的参数传给回调函数"><a href="#spread-将一个数组作为一个单独的参数传给回调函数" class="headerlink" title="spread() 将一个数组作为一个单独的参数传给回调函数"></a>spread() 将一个数组作为一个单独的参数传给回调函数</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">it('.spread() - spread an array as individual args to callback function', () => {</span><br><span class="line"> // https://on.cypress.io/spread</span><br><span class="line"> const arr = ['foo', 'bar', 'baz']</span><br><span class="line"> </span><br><span class="line"> cy.wrap(arr).spread((foo, bar, baz) => {</span><br><span class="line"> expect(foo).to.eq('foo');</span><br><span class="line"> expect(bar).to.eq('bar');</span><br><span class="line"> expect(baz).to.eq('baz');</span><br><span class="line"> });</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h2 id="getCookie-获得浏览器一个-cookie"><a href="#getCookie-获得浏览器一个-cookie" class="headerlink" title="getCookie() 获得浏览器一个 cookie"></a>getCookie() 获得浏览器一个 cookie</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">it('cy.getCookie() - get a browser cookie', () => {</span><br><span class="line"> cy.get('#getCookie .set-a-cookie').click();</span><br><span class="line"> cy.getCookie('token').should('have.property', 'value', '123ABC');</span><br><span class="line">})</span><br></pre></td></tr></table></figure><p>## getCookies() 获得浏览器的所有 Cookie</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">it("cy.getCookie() - get a browser cookie", () => {</span><br><span class="line"> cy.get('#getCookie .set-a-cookie').click();</span><br><span class="line"> cy.getCookies().should('have.length', 1).should((cookies) => {</span><br><span class="line"> expect(cookies[0]).to.have.property('value', '123ABC');</span><br><span class="line"> expect(cookies[0]).to.have.property('httpOnly', false);</span><br><span class="line"> expect(cookies[0]).to.have.property('secure', false);</span><br><span class="line"> expect(cookies[0]).to.have.property('domain');</span><br><span class="line"> expect(cookies[0]).to.have.property('path');</span><br><span class="line"> })</span><br><span class="line">})</span><br></pre></td></tr></table></figure><h2 id="setCookie-设置一个浏览器-Cookie"><a href="#setCookie-设置一个浏览器-Cookie" class="headerlink" title="setCookie() 设置一个浏览器 Cookie"></a>setCookie() 设置一个浏览器 Cookie</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">it('cy.setCookie() - set a browser cookie', () => {</span><br><span class="line"> cy.getCookies().should('be.empty'); </span><br><span class="line"> cy.setCookie('foo', 'bar'); </span><br><span class="line"> cy.getCookie('foo').should('have.property', 'value', 'bar');</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><h2 id="clearCookie-清除一个浏览器-Cookie"><a href="#clearCookie-清除一个浏览器-Cookie" class="headerlink" title="clearCookie() 清除一个浏览器 Cookie"></a>clearCookie() 清除一个浏览器 Cookie</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">it('cy.clearCookie() - clear a browser cookie', () => {</span><br><span class="line"> cy.getCookie('token').should('be.null');</span><br><span class="line"> cy.get('#clearCookie .set-a-cookie').click();</span><br><span class="line"> cy.getCookie('token').should('have.property', 'value', '123ABC');</span><br><span class="line"> cy.clearCookie('token').should('be.null');</span><br><span class="line"> cy.getCookie('token').should('be.null');</span><br><span class="line"> });</span><br></pre></td></tr></table></figure><h2 id="clearCookies-清除浏览器的所有的-Cookie"><a href="#clearCookies-清除浏览器的所有的-Cookie" class="headerlink" title="clearCookies() 清除浏览器的所有的 Cookie"></a>clearCookies() 清除浏览器的所有的 Cookie</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">it('cy.clearCookies() - clear browser cookies', () => {</span><br><span class="line"> cy.getCookies().should('be.empty');</span><br><span class="line"> cy.get('#clearCookies .set-a-cookie').click();</span><br><span class="line"> cy.getCookies().should('have.length', 1);</span><br><span class="line"> cy.clearCookies();</span><br><span class="line"> cy.getCookies().should('be.empty');</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h2 id="children-获得子-DOM-元素"><a href="#children-获得子-DOM-元素" class="headerlink" title="children() 获得子 DOM 元素"></a>children() 获得子 DOM 元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">it('.children() - get child DOM elements', () => {</span><br><span class="line"> cy.get('.traversal-breadcrumb')</span><br><span class="line"> .children('.active')</span><br><span class="line"> .should('contain', 'Data');</span><br><span class="line"> });</span><br></pre></td></tr></table></figure><h2 id="closest-获得最近的祖先-DOM-元素"><a href="#closest-获得最近的祖先-DOM-元素" class="headerlink" title="closest() 获得最近的祖先 DOM 元素"></a>closest() 获得最近的祖先 DOM 元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">it('.closest() - get closest ancestor DOM element', () => {</span><br><span class="line"> cy.get('.traversal-badge')</span><br><span class="line"> .closest('ul')</span><br><span class="line"> .should('have.class', 'list-group')</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><h2 id="eq-获取一个明确索引的DOM元素"><a href="#eq-获取一个明确索引的DOM元素" class="headerlink" title="eq() 获取一个明确索引的DOM元素"></a>eq() 获取一个明确索引的DOM元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">it('.eq() - get a DOM element at a specific index', () => {</span><br><span class="line"> cy.get('.traversal-list>li')</span><br><span class="line"> .eq(1).should('contain', 'siamese')</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><h2 id="filter-获取特定选择器匹配的-DOM-元素"><a href="#filter-获取特定选择器匹配的-DOM-元素" class="headerlink" title="filter() 获取特定选择器匹配的 DOM 元素"></a>filter() 获取特定选择器匹配的 DOM 元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">it('.filter() - get DOM elements that match the selector', () => {</span><br><span class="line"> cy.get('.traversal-nav>li')</span><br><span class="line"> .filter('.active').should('contain', 'About')</span><br><span class="line">})</span><br></pre></td></tr></table></figure><h2 id="find-获取选择器的后代-DOM-元素"><a href="#find-获取选择器的后代-DOM-元素" class="headerlink" title="find() 获取选择器的后代 DOM 元素"></a>find() 获取选择器的后代 DOM 元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">it('.find() - get descendant DOM elements of the selector', () => {</span><br><span class="line"> cy.get('.traversal-pagination')</span><br><span class="line"> .find('li').find('a')</span><br><span class="line"> .should('have.length', 7)</span><br><span class="line">})</span><br></pre></td></tr></table></figure><h2 id="first-获取第一个-DOM-元素"><a href="#first-获取第一个-DOM-元素" class="headerlink" title="first() 获取第一个 DOM 元素"></a>first() 获取第一个 DOM 元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">it('.first() - get first DOM element', () => {</span><br><span class="line"> cy.get('.traversal-table td')</span><br><span class="line"> .first().should('contain', '1')</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><h2 id="last-获取最后一个-DOM-元素"><a href="#last-获取最后一个-DOM-元素" class="headerlink" title="last() 获取最后一个 DOM 元素"></a>last() 获取最后一个 DOM 元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">it('.last() - get last DOM element', () => {</span><br><span class="line"> cy.get('.traversal-buttons .btn')</span><br><span class="line"> .last().should('contain', 'Submit')</span><br><span class="line">})</span><br></pre></td></tr></table></figure><h2 id="next-获得下一个兄弟-DOM-元素"><a href="#next-获得下一个兄弟-DOM-元素" class="headerlink" title="next() 获得下一个兄弟 DOM 元素"></a>next() 获得下一个兄弟 DOM 元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">it('.next() - get next sibling DOM element', () => {</span><br><span class="line"> cy.get('.traversal-ul')</span><br><span class="line"> .contains('apples').next().should('contain', 'oranges')</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><p>## nextAll() 获取该元素的所有下一个兄弟元素</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">it('.nextAll() - get all next sibling DOM elements', () => {</span><br><span class="line"> cy.get('.traversal-next-all')</span><br><span class="line"> .contains('oranges')</span><br><span class="line"> .nextAll().should('have.length', 3)</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><h2 id="nextUntil-获取该元素的所有下一个元素直到另一个元素为止"><a href="#nextUntil-获取该元素的所有下一个元素直到另一个元素为止" class="headerlink" title="nextUntil() 获取该元素的所有下一个元素直到另一个元素为止"></a>nextUntil() 获取该元素的所有下一个元素直到另一个元素为止</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">it('.nextUntil() - get next sibling DOM elements until next el', () => {</span><br><span class="line"> cy.get('#veggies')</span><br><span class="line"> .nextUntil('#nuts').should('have.length', 3)</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><h2 id="not-从元素集合中删除元素"><a href="#not-从元素集合中删除元素" class="headerlink" title="not() 从元素集合中删除元素"></a>not() 从元素集合中删除元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">it('.not() - remove DOM elements from set of DOM elements', () => {</span><br><span class="line"> cy.get('.traversal-disabled .btn')</span><br><span class="line"> .not('[disabled]').should('not.contain', 'Disabled')</span><br><span class="line">})</span><br></pre></td></tr></table></figure><h2 id="parent-获取上一级父-DOM-元素"><a href="#parent-获取上一级父-DOM-元素" class="headerlink" title="parent() 获取上一级父 DOM 元素"></a>parent() 获取上一级父 DOM 元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">it('.parent() - get parent DOM element from DOM elements', () => {</span><br><span class="line"> cy.get('.traversal-mark')</span><br><span class="line"> .parent().should('contain', 'Morbi leo risus')</span><br><span class="line">})</span><br></pre></td></tr></table></figure><h2 id="parents-从-DOM-元素中获取父-DOM-元素"><a href="#parents-从-DOM-元素中获取父-DOM-元素" class="headerlink" title="parents() 从 DOM 元素中获取父 DOM 元素"></a>parents() 从 DOM 元素中获取父 DOM 元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">it('.parents() - get parent DOM elements from DOM elements', () => {</span><br><span class="line"> cy.get('.traversal-cite')</span><br><span class="line"> .parents().should('match', 'blockquote')</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><h2 id="parentsUntil-从-DOM-元素获得父-DOM-元素,直到-el"><a href="#parentsUntil-从-DOM-元素获得父-DOM-元素,直到-el" class="headerlink" title="parentsUntil() 从 DOM 元素获得父 DOM 元素,直到 el"></a>parentsUntil() 从 DOM 元素获得父 DOM 元素,直到 el</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">it('.parentsUntil() - get parent DOM elements from DOM elements until el', () => {</span><br><span class="line"> cy.get('.clothes-nav')</span><br><span class="line"> .find('.active')</span><br><span class="line"> .parentsUntil('.clothes-nav')</span><br><span class="line"> .should('have.length', 2)</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><h2 id="prev-获得前一兄弟-DOM-元素"><a href="#prev-获得前一兄弟-DOM-元素" class="headerlink" title="prev() 获得前一兄弟 DOM 元素"></a>prev() 获得前一兄弟 DOM 元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">it('.prev() - get previous sibling DOM element', () => {</span><br><span class="line"> cy.get('.birds').find('.active')</span><br><span class="line"> .prev().should('contain', 'Lorikeets')</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><h2 id="prevAll-获得前面所有兄弟-DOM-元素"><a href="#prevAll-获得前面所有兄弟-DOM-元素" class="headerlink" title="prevAll() 获得前面所有兄弟 DOM 元素"></a>prevAll() 获得前面所有兄弟 DOM 元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">it('.prevAll() - get all previous sibling DOM elements', () => {</span><br><span class="line"> cy.get('.fruits-list').find('.third')</span><br><span class="line"> .prevAll().should('have.length', 2)</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><p>## prevUntil() 获得前面的直到 el 的所有兄弟 DOM 元素</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">it('.prevUntil() - get all previous sibling DOM elements until el', () => {</span><br><span class="line"> cy.get('.foods-list').find('#nuts')</span><br><span class="line"> .prevUntil('#veggies').should('have.length', 3)</span><br><span class="line">})</span><br></pre></td></tr></table></figure><h2 id="siblings-获得所有的兄弟-DOM-元素-不包含本身元素"><a href="#siblings-获得所有的兄弟-DOM-元素-不包含本身元素" class="headerlink" title="siblings() 获得所有的兄弟 DOM 元素 (不包含本身元素)"></a>siblings() 获得所有的兄弟 DOM 元素 (不包含本身元素)</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">it('.siblings() - get all sibling DOM elements', () => {</span><br><span class="line"> cy.get('.traversal-pills .active')</span><br><span class="line"> .siblings().should('have.length', 2)</span><br><span class="line">})</span><br></pre></td></tr></table></figure>]]></content:encoded>
<comments>https://qiyanan.com/2019/09/13/Cypress-%E5%B8%B8%E7%94%A8%E5%87%BD%E6%95%B0/#disqus_thread</comments>
</item>
<item>
<title>TypeScript-AdvancedTypes</title>
<link>https://qiyanan.com/2019/09/13/TypeScript-AdvancedTypes/</link>
<guid>https://qiyanan.com/2019/09/13/TypeScript-AdvancedTypes/</guid>
<pubDate>Fri, 13 Sep 2019 05:38:22 GMT</pubDate>
<description>
<h1 id="Advanced-Types"><a href="#Advanced-Types" class="headerlink" title="Advanced Types"></a>Advanced Types</h1><h2 id="Intersection-Type
</description>
<content:encoded><![CDATA[<h1 id="Advanced-Types"><a href="#Advanced-Types" class="headerlink" title="Advanced Types"></a>Advanced Types</h1><h2 id="Intersection-Types-交叉类型"><a href="#Intersection-Types-交叉类型" class="headerlink" title="Intersection Types(交叉类型)"></a>Intersection Types(交叉类型)</h2><p>交叉类型是将多个类型合并为一个类型,这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性,例如, Person & Serializable & Loggable同时是 Person 和 Serializable 和 Loggable。就是说这个类型的对象同时有了三种类型的成员。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">function extend<First, Second>(first: First, second: Second): First & Second {</span><br><span class="line"> const result: Partial<First & Second> = {};</span><br><span class="line"> for (const prop in first) {</span><br><span class="line"> if (first.hasOwnProperty(prop)) {</span><br><span class="line"> (result as First)[prop] = first[prop];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> for (const prop in second) {</span><br><span class="line"> if (second.hasOwnProperty(prop)) {</span><br><span class="line"> (result as Second)[prop] = second[prop];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> return result as First & Second;</span><br><span class="line">}</span><br><span class="line">class Person {</span><br><span class="line"> constructor(public name: string) { }</span><br><span class="line">}</span><br><span class="line">interface Loggable {</span><br><span class="line"> log(name: string): void;</span><br><span class="line">}</span><br><span class="line">class ConsoleLogger implements Loggable {</span><br><span class="line"> log(name:string) {</span><br><span class="line"> console.log( `Hello, I'm ${name}.` );</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">const jim = extend(new Person('Jim'), ConsoleLogger.prototype);</span><br><span class="line">jim.log(jim.name);</span><br></pre></td></tr></table></figure><h2 id="Union-Types"><a href="#Union-Types" class="headerlink" title="Union Types"></a>Union Types</h2><p>联合类型表示一个值可以是几种类型之一,我们用竖线(|)分隔每个类型,所以 number | string | boolean 表示一个值可以是 number,string,或 boolean。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">interface Bird {</span><br><span class="line"> fly();</span><br><span class="line"> layEggs();</span><br><span class="line">}</span><br><span class="line">interface Fish {</span><br><span class="line"> swim();</span><br><span class="line"> layEggs();</span><br><span class="line">}</span><br><span class="line">function getSmallPet(): Fish | Bird {</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">let pet = getSmallPet();</span><br><span class="line">pet.layEggs();</span><br><span class="line">pet.swim();</span><br></pre></td></tr></table></figure><p><strong>如果我们有一个值是联合类型,我们只能访问此联合类型的所有类型里共有的成员</strong></p><h2 id="Type-Guards-and-Differentiating-Types-类型保护和区分类型"><a href="#Type-Guards-and-Differentiating-Types-类型保护和区分类型" class="headerlink" title="Type Guards and Differentiating Types(类型保护和区分类型)"></a>Type Guards and Differentiating Types(类型保护和区分类型)</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">let pet = getSmallPet();</span><br><span class="line">if ((<Fish>pet).swim) {</span><br><span class="line"> (<Fish>pet).swim;</span><br><span class="line">} else {</span><br><span class="line"> (<Bird>pet).fly();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="User-Defined-type-Guards"><a href="#User-Defined-type-Guards" class="headerlink" title="User-Defined type Guards"></a>User-Defined type Guards</h3><p>这里可以注意到我们不得不多次使用类型断言,假若我们一旦检查过类型,就能在之后的每个分支里清楚地知道 pet 的类型就好了。<br>TypeScript里的类保护机制让他成为了现实,类保护就是一些表达式,他们会在运行时检查以确保在某个作用域里的类型。要定义一个类型保护,我们只要简单的定义一个函数,它的返回值就是一个类型谓词。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">function isFish(pet: Fish | Bird): pet is Fish {</span><br><span class="line"> return (pet as Fish).swim !== undefined;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在这个例子里,pet is Fish 就是类型谓词,谓词为 parameterName is Type 这种形式,parameterName 必须是来自于当前函数签名里的一个参数名</p><p>每当使用一些变量调用 isFish 时,TypeScript 会将变量缩减为那个具体的类型,只要这个类型与变量的原始类型是兼容的。</p><h3 id="using-the-in-operator"><a href="#using-the-in-operator" class="headerlink" title="using the in operator"></a>using the in operator</h3><p>in 操作符现在充当类型的窄化表达式。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">function move(pet: Fish | Bird) {</span><br><span class="line"> if ("swim" in pet) {</span><br><span class="line"> return pet.swim();</span><br><span class="line"> }</span><br><span class="line"> return pet.fly();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>typeof type guards</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">function isNumber(x: any): x is number {</span><br><span class="line"> return typeof x === "number";</span><br><span class="line">}</span><br><span class="line">function isString(x: any): x is string {</span><br><span class="line"> return typeof x === "string";</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">function padLeft(value: string, padding: string | number) {</span><br><span class="line"> if (isNumber(padding)) {</span><br><span class="line"> return Array(padding + 1).join("") + value;</span><br><span class="line"> }</span><br><span class="line"> if (isString(padding)) {</span><br><span class="line"> return padding + value;</span><br><span class="line"> }</span><br><span class="line"> throw new Error( `Expected string or number,got'${padding}', ` )</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>然而,必须要定义一个函数来判断类型是否是原始类型,这太痛苦了,幸运的是,现在我们不必将 typeof x === “number” 抽象成一个函数,因为 TypeScript 可以将它识别为一个类型保护,也就是说我们可以直接在代码里检查类型</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">function padLeft(value: string, padding: string | number) {</span><br><span class="line"> if (typeof padding === "number") {</span><br><span class="line"> return Array(padding + 1).join(" ") + value;</span><br><span class="line"> }</span><br><span class="line"> if (typeof padding === "string") {</span><br><span class="line"> return padding + value</span><br><span class="line"> }</span><br><span class="line"> throw new Error( `Expected string or number,got'${padding}', ` )</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong><em>这些 typeof 类型保护只有两种形式被识别: typeof v ===”typename” and typeof v !== “typename”, “typename” 必须是”number”, “string”, “boolean”, or “symbol”,但是 TypeScript 并不会组织你与其他字符串比较,语言不会把那些识别为类型保护</em></strong></p><h2 id="instanceof-type-guards"><a href="#instanceof-type-guards" class="headerlink" title="instanceof type guards"></a>instanceof type guards</h2><p>instanceof 类型保护是通过构造函数来细化类型的一种方式</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">interface Padder {</span><br><span class="line"> getPaddingString(): string;</span><br><span class="line">}</span><br><span class="line">class SpaceRepeatingPadder implements Padder {</span><br><span class="line"> constructor(private numSpaces: number) { }</span><br><span class="line"> getPaddingString() {</span><br><span class="line"> return Array(this.numSpaces + 1).join(" ");</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">class StringPadder implements Padder {</span><br><span class="line"> constructor(private value: string) { }</span><br><span class="line"> getPaddingString() {</span><br><span class="line"> return this.value;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">function getRandomPadder() {</span><br><span class="line"> return Math.random() < 0.5 ? new SpaceRepeatingPadder(4) : new StringPadder(" ");</span><br><span class="line">}</span><br><span class="line">let padder: Padder = getRandomPadder();</span><br><span class="line">if (padder instanceof SpaceRepeatingPadder) {</span><br><span class="line"> padder;</span><br><span class="line">}</span><br><span class="line">if (padder instanceof StringPadder) {</span><br><span class="line"> padder;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>instanceof 的右侧要求一个构造函数,TypeScript将细化为:</p><ol><li>此构造函数的 prototype 属性的类型,如果它的类型不为 any 的话。</li><li>构造签名所返回的类型的联合。</li></ol><h2 id="Nullable-types"><a href="#Nullable-types" class="headerlink" title="Nullable types"></a>Nullable types</h2><p>TypeScript 具有两种哦就那个特殊的类型,null 和 undefined,他们分别具有值 null 和 undefined,默认情况下,类型检查器认为 null 与 undefined 可以赋值给任何类型。null 与 undefined 是所有其他类型的一个有效值。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">let s = "foo";</span><br><span class="line">let sn: string | null = "bar";</span><br><span class="line">sn = null;</span><br><span class="line">sn = undefined;// Error</span><br></pre></td></tr></table></figure>]]></content:encoded>
<comments>https://qiyanan.com/2019/09/13/TypeScript-AdvancedTypes/#disqus_thread</comments>
</item>
<item>
<title>TypeScript-Type Compatibility</title>
<link>https://qiyanan.com/2019/09/13/TypeScript-TypeCompatibility/</link>
<guid>https://qiyanan.com/2019/09/13/TypeScript-TypeCompatibility/</guid>
<pubDate>Fri, 13 Sep 2019 02:32:28 GMT</pubDate>
<description>
<h1 id="Type-Compatibility"><a href="#Type-Compatibility" class="headerlink" title="Type Compatibility"></a>Type Compatibility</h1><p>TypeSc
</description>
<content:encoded><![CDATA[<h1 id="Type-Compatibility"><a href="#Type-Compatibility" class="headerlink" title="Type Compatibility"></a>Type Compatibility</h1><p>TypeScript 中的类型兼容性基于结构化子类型,结构类型是一种仅基于其成员关联类型的方法,这与名义类型形成了对比</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">interface Named {</span><br><span class="line"> name: string;</span><br><span class="line">}</span><br><span class="line">class Person {</span><br><span class="line"> name: string;</span><br><span class="line"> constructor(name:string){</span><br><span class="line"> this.name=name;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">let p: Named;</span><br><span class="line">p = new Person("");</span><br></pre></td></tr></table></figure><p><strong>TypeScript 的类型系统允许某些在编译阶段无法确认其安全性的操作</strong></p><h2 id="Starting-out"><a href="#Starting-out" class="headerlink" title="Starting out"></a>Starting out</h2><p>TypeScript 结构化类型系统的基本规则是,如果 x 要兼容 y,那么 y 至少具有 x 相同的属性</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">interface Named {</span><br><span class="line"> name: string;</span><br><span class="line">}</span><br><span class="line">let x: Named;</span><br><span class="line">let y = { name: "Alice", Location: "Seattle" };</span><br><span class="line">x = y;</span><br></pre></td></tr></table></figure><h2 id="Comparing-two-functions"><a href="#Comparing-two-functions" class="headerlink" title="Comparing two functions"></a>Comparing two functions</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">let x = (a: number) => 0;</span><br><span class="line">let y = (b: number, s: string) => 0;</span><br><span class="line">y = x;</span><br><span class="line">x = y;// Error</span><br></pre></td></tr></table></figure><p>要查看 x 是否能赋值给 y,首先看他们的参数列表,x 的每个参数必须能在 y 里找到对应类型的参数。注意的是参数的名字相同与否无所谓,只看他们的类型,这里,x 的每个参数在 y 中都能找到对应的参数,所以允许赋值。<br>下面来看看如何让处理返回值类型,创建两个仅是返回值类型不同的函数。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">let x = () => ({ name: "Alice" });</span><br><span class="line">let y = () => ({ name: "Alice", location: "Seattle" });</span><br><span class="line">x=y;</span><br><span class="line">y=x; // Error</span><br></pre></td></tr></table></figure><p><strong>类型系统强制原函数的返回值类型必须是目标函数返回值类型的子类型</strong></p><h2 id="Optional-Parameters-and-Rest-Parameters"><a href="#Optional-Parameters-and-Rest-Parameters" class="headerlink" title="Optional Parameters and Rest Parameters"></a>Optional Parameters and Rest Parameters</h2><p>当比较函数兼容性的时候, 可选参数和必选参数是可互换的。<br><strong>源类型上有额外的可选参数不是错误,目标类型的可选参数在源类型里没有对应的参数也不是错误</strong><br>当一个函数有剩余参数时,它被当作无限个可选参数。<br>有一个好的例子,常见的函数接受一个回调函数并用于对于程序员来说是可预知的参数但对类型系统来说是不确定的参数</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function invokeLater(args: any[], callback: (...args: any[]) => void) {</span><br><span class="line">}</span><br><span class="line">invokeLater([1, 2], (x, y) => console.log(x + "," + y));</span><br><span class="line">invokeLater([1, 2], (x?, y?) => console.log(x + "," + y));</span><br></pre></td></tr></table></figure><h2 id="Functions-with-overloads"><a href="#Functions-with-overloads" class="headerlink" title="Functions with overloads"></a>Functions with overloads</h2><p>对于有重载的函数,源函数的每个重载都要在目标函数上找到对应的函数签名,这确保了目标函数可以在所有源函数可调用的地方调用</p><h2 id="Enums"><a href="#Enums" class="headerlink" title="Enums"></a>Enums</h2><p>枚举类型与数字类型兼容,并且数字类型与枚举类型兼容,不同枚举之间是不兼容的</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">enum Status { Ready, Waiting };</span><br><span class="line">enum Color { Red, Blue, Green };</span><br><span class="line">let status = Status.Ready;</span><br><span class="line">status=Color.Green; // Error</span><br></pre></td></tr></table></figure><h2 id="Classes"><a href="#Classes" class="headerlink" title="Classes"></a>Classes</h2><p>类有静态部分和实例部分的类型. 当比较两个类类型的对象时, <strong>只有实例成员会被比较,静态函数和构造函数不在比较的范围内</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">class Animal {</span><br><span class="line"> feet: number;</span><br><span class="line"> constructor(name: string, numFeet: number) {</span><br><span class="line"> this.feet = numFeet;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">class Size {</span><br><span class="line"> feet: number;</span><br><span class="line"> constructor(numFeet: number) {</span><br><span class="line"> this.feet = numFeet;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">let a: Animal;</span><br><span class="line">let s: Size;</span><br><span class="line">a = s;</span><br><span class="line">s = a;</span><br></pre></td></tr></table></figure><h3 id="Private-and-protected-members-in-classes"><a href="#Private-and-protected-members-in-classes" class="headerlink" title="Private and protected members in classes"></a>Private and protected members in classes</h3><p>类的私有成员和受保护成员会影响兼容性, 但检查类实例的兼容时,如果目标类型包含一个私有成员,如果目标类型包含一个私有成员,那么源类型必须包含来自同一个类的这个私有成员,同样地,这条规则也适用于包含受保护成员实例的类型检查,这允许子类赋值给父类,但是不能与具有相同形状的不同继承层次结构的类兼容。</p><p>## Generics<br>因为 TypeScript 是结构性的类型系统,类型参数只影响使用其作为类型一部分的结果类型。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">interface Empty<T> {</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">let x: Empty<number>;</span><br><span class="line">let y: Empty<string>;</span><br><span class="line">x = y;</span><br></pre></td></tr></table></figure><p>通过给该接口添加一个成员更改这个个例子,可以看到是如何工作的。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">interface Empty<T> {</span><br><span class="line"> data: T;</span><br><span class="line">}</span><br><span class="line">let x: Empty<number>;</span><br><span class="line">let y: Empty<string>;</span><br><span class="line">x = y; // Error</span><br></pre></td></tr></table></figure><p>对于没指定泛型类型的泛型参数时,会把所有泛型参数当成 any 比较。然后用结果类型进行比较</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">let identity = function <T>(x: T): T {</span><br><span class="line"> return x;</span><br><span class="line">}</span><br><span class="line">let reverse = function <U>(y: U): U {</span><br><span class="line"> return y;</span><br><span class="line">}</span><br><span class="line">identity = reverse;</span><br></pre></td></tr></table></figure>]]></content:encoded>
<comments>https://qiyanan.com/2019/09/13/TypeScript-TypeCompatibility/#disqus_thread</comments>
</item>
<item>
<title>TypeScript-TypeInference</title>
<link>https://qiyanan.com/2019/09/10/TypeScript-TypeInference/</link>
<guid>https://qiyanan.com/2019/09/10/TypeScript-TypeInference/</guid>
<pubDate>Tue, 10 Sep 2019 01:38:47 GMT</pubDate>
<description>
<h1 id="Type-Inference"><a href="#Type-Inference" class="headerlink" title="Type Inference"></a>Type Inference</h1><h2 id="Basics"><a href="
</description>
<content:encoded><![CDATA[<h1 id="Type-Inference"><a href="#Type-Inference" class="headerlink" title="Type Inference"></a>Type Inference</h1><h2 id="Basics"><a href="#Basics" class="headerlink" title="Basics"></a>Basics</h2><p>TypeScript 里,在有些没有明确指出类型的地方,类型推论会帮助提供类型</p><p><code>let x = 3;</code></p><h2 id="Best-common-type"><a href="#Best-common-type" class="headerlink" title="Best common type"></a>Best common type</h2><p>当需要从几个表达式中推断类型的时候,会使用这些表达式的类型来推断出一个最合适的通用类型</p><p><code>let x = [0, 1, null];</code></p><p>计算通用类型算法会考虑所有的候选类型,并给出一个兼容所有候选类型的类型</p><h2 id="Contextual-Typing"><a href="#Contextual-Typing" class="headerlink" title="Contextual Typing"></a>Contextual Typing</h2><p>上下文类型在很多情况下使用到,通常包含函数的参数,赋值表达式的右边,类型断言,对象成员和数组字面量和返回值语句,上下文类型也会做为最佳通用类型的候选类型</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">class Animal{}</span><br><span class="line">class Rhino extends Animal{}</span><br><span class="line">class Elephant extends Animal{}</span><br><span class="line">class Snake extends Animal{}</span><br><span class="line">function createZoo():Animal[]{</span><br><span class="line"> return [new Rhino(), new Elephant(), new Snake()];</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content:encoded>
<comments>https://qiyanan.com/2019/09/10/TypeScript-TypeInference/#disqus_thread</comments>
</item>
<item>
<title>TypeScript-Enums</title>
<link>https://qiyanan.com/2019/09/09/TypeScript-Enums/</link>
<guid>https://qiyanan.com/2019/09/09/TypeScript-Enums/</guid>
<pubDate>Mon, 09 Sep 2019 06:33:19 GMT</pubDate>
<description>
<h1 id="Enums"><a href="#Enums" class="headerlink" title="Enums"></a>Enums</h1><p>使用枚举我们可以定义一些带有名字的变量,使用枚举我们可以清晰地表达意图或者创建一组有区别的用例,TypeScript
</description>
<content:encoded><![CDATA[<h1 id="Enums"><a href="#Enums" class="headerlink" title="Enums"></a>Enums</h1><p>使用枚举我们可以定义一些带有名字的变量,使用枚举我们可以清晰地表达意图或者创建一组有区别的用例,TypeScript 支持数字的和基于字符串的枚举</p><h2 id="Numeric-enums"><a href="#Numeric-enums" class="headerlink" title="Numeric enums"></a>Numeric enums</h2><p>可以使用 enum 关键字来定义一个 枚举</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">enum Direction {</span><br><span class="line"> Up = 1,</span><br><span class="line"> Down,</span><br><span class="line"> Left,</span><br><span class="line"> Right,</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>我们可以完全不使用初始化器</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">enum Direction{</span><br><span class="line"> Up,</span><br><span class="line"> Down,</span><br><span class="line"> Left,</span><br><span class="line"> Right,</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>使用枚举很简单:通过枚举的属性来访问枚举成员,使用枚举的名字声明类型</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">enum Responses {</span><br><span class="line"> No,</span><br><span class="line"> Yes,</span><br><span class="line">}</span><br><span class="line">function Respond(recipient:string,message:Responses):void{</span><br><span class="line">}</span><br><span class="line">Respond("Princess Caroline",Responses.Yes)</span><br></pre></td></tr></table></figure><h2 id="String-enums"><a href="#String-enums" class="headerlink" title="String enums"></a>String enums</h2><p>在一个字符串枚举里,每个成员都必须用字符串字面量,或另外一个字符串枚举成员来进行初始化<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">enum Direction {</span><br><span class="line"> Up = "UP",</span><br><span class="line"> Down = "DOWN",</span><br><span class="line"> Left = "LEFT",</span><br><span class="line"> Right = "RIGHT",</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h2 id="Heterogeneous-enums(异构枚举)"><a href="#Heterogeneous-enums(异构枚举)" class="headerlink" title="Heterogeneous enums(异构枚举)"></a>Heterogeneous enums(异构枚举)</h2><p>从技术角度来说,枚举可以混合字符串和数字成员</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">enum BooleanLikeHeterogeneousEnum {</span><br><span class="line"> No = 0,</span><br><span class="line"> Yes = "YES",</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Computed-and-constant-members"><a href="#Computed-and-constant-members" class="headerlink" title="Computed and constant members"></a>Computed and constant members</h2><p>每个枚举成员都有一个值,它可以是常量或就上出来的</p><ul><li>它是枚举的第一个成员且没有初始化器,这种情况下他被赋值 0</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">enum E { X }</span><br></pre></td></tr></table></figure><ul><li>它不带有初始化器且它之前的枚举成员是一个数字常量,这种情况下,当前枚举成员的值为他上一个枚举成员的值加 1</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">enum E1 { X, Y, Z }</span><br><span class="line"></span><br><span class="line">enum E2 {</span><br><span class="line"> A = 1, B, C</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>枚举成员使用常量枚举表达式初始化,常数枚举表达式是 TypeScript 表达式的子集,它可以在编译阶段求值,给一个表达式满足下面条件之一时,他就是一个常量枚举表达式:</li></ul><ol><li>一个枚举表达式字面量(主要是字符串字面量或数字字面量)</li><li>一个对之前定义的常量枚举成员的引用(可以是在不同的枚举类型中定义的)</li><li>带括号的常量枚举表达式</li><li>一元运算符 +, -, ~ 其中之一应用在了常量枚举表达式 </li><li>常量枚举表达式作为二元运算符 +, -, *, /, %, <<, >>, >>>, &, |, ^ 的操作对象,若常数枚举表达式求值后卫 NaN 或 Infinity,则会在编译阶段报错<br>所有其他情况的枚举成员被当作是需要计算得出的值<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">enum FileAccess {</span><br><span class="line"> None,</span><br><span class="line"> Read = 1 << 1,</span><br><span class="line"> Write = 1 << 2,</span><br><span class="line"> ReadWrite = Read | Write,</span><br><span class="line"> G = "123".length</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ol><h2 id="Union-enums-and-enum-member-types"><a href="#Union-enums-and-enum-member-types" class="headerlink" title="Union enums and enum member types"></a>Union enums and enum member types</h2><p>存在一种特殊的非计算的常量枚举成员的子集:字面量枚举成员,字面量枚举成员是指不带有初始值的常量枚举成员,或者是值被初始化为</p><ul><li>任何字符串字面量(e.g. “foo”, “bar”, “baz”)</li><li>任何数字字面量(e.g. 1, 100)</li><li>应用了一元 - 符号的数字字面量(e.g. -1, -100)</li></ul><p>当所有枚举成员都拥有字面量枚举值时,它就带有可以一种特殊的语义。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">enum ShapeKind {</span><br><span class="line"> Circle,</span><br><span class="line"> Square,</span><br><span class="line">}</span><br><span class="line">interface Circle {</span><br><span class="line"> kind: ShapeKind.Circle;</span><br><span class="line"> radius: number</span><br><span class="line">}</span><br><span class="line">interface Square {</span><br><span class="line"> kind: ShapeKind.Square</span><br><span class="line"> sideLength: number;</span><br><span class="line">}</span><br><span class="line">let c: Circle = {</span><br><span class="line"> kind: ShapeKind.Circle,</span><br><span class="line"> radius: 100,</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Enums-at-runtime"><a href="#Enums-at-runtime" class="headerlink" title="Enums at runtime"></a>Enums at runtime</h2><p>枚举是在运行时真正存在的对象</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">enum E {</span><br><span class="line"> X, Y, Z</span><br><span class="line">}</span><br><span class="line">function f(obj: { X: number }) {</span><br><span class="line"> return obj.X;</span><br><span class="line">}</span><br><span class="line">f(E);</span><br></pre></td></tr></table></figure><h2 id="Enums-at-compile-time"><a href="#Enums-at-compile-time" class="headerlink" title="Enums at compile time"></a>Enums at compile time</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">enum LogLevel {</span><br><span class="line"> ERROR, WARN, INFO, DEBUG</span><br><span class="line">}</span><br><span class="line">type LogLevelStrings = keyof typeof LogLevel;</span><br><span class="line">function printImportant(key: LogLevelStrings, message: string) {</span><br><span class="line"> const num = LogLevel[key];</span><br><span class="line"> if (num <= LogLevel.WARN) {</span><br><span class="line"> console.log('Log level kry is: ', key);</span><br><span class="line"> console.log('Log level Value is: ', num);</span><br><span class="line"> console.log('Log level message is: ', message);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">printImportant('ERROR', 'This is a message');</span><br></pre></td></tr></table></figure><h2 id="Reverse-mappings"><a href="#Reverse-mappings" class="headerlink" title="Reverse mappings"></a>Reverse mappings</h2><p>除了创建一个以属性名做为对象成员的对象之外,数字枚举成员还具有了反向映射,从枚举值到枚举名字</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">enum Enum {</span><br><span class="line"> A</span><br><span class="line">}</span><br><span class="line">let a = Enum.A;</span><br><span class="line">let nameOfA = Enum[a];</span><br></pre></td></tr></table></figure><h2 id="const-enums"><a href="#const-enums" class="headerlink" title="const enums"></a>const enums</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">const enum Directions{</span><br><span class="line"> Up,</span><br><span class="line"> Down,</span><br><span class="line"> Left,</span><br><span class="line"> Right,</span><br><span class="line">}</span><br><span class="line">let directions = [Directions.Up,Directions.Down,Directions.Left,Directions.Right]</span><br></pre></td></tr></table></figure><h2 id="Ambient-enums(外部枚举)"><a href="#Ambient-enums(外部枚举)" class="headerlink" title="Ambient enums(外部枚举)"></a>Ambient enums(外部枚举)</h2><p>Ambient enums</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">declare enum Enum {</span><br><span class="line"> A = 1,</span><br><span class="line"> B,</span><br><span class="line"> C = 2</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content:encoded>
<comments>https://qiyanan.com/2019/09/09/TypeScript-Enums/#disqus_thread</comments>
</item>
<item>
<title>TypeScript-Generic</title>
<link>https://qiyanan.com/2019/09/09/TypeScript-Generic/</link>
<guid>https://qiyanan.com/2019/09/09/TypeScript-Generic/</guid>
<pubDate>Mon, 09 Sep 2019 05:35:00 GMT</pubDate>
<description>
<h1 id="Generics"><a href="#Generics" class="headerlink" title="Generics"></a>Generics</h1><p>我们可以使用 any 类型来定义函数</p>
<figure class="highligh
</description>
<content:encoded><![CDATA[<h1 id="Generics"><a href="#Generics" class="headerlink" title="Generics"></a>Generics</h1><p>我们可以使用 any 类型来定义函数</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">function identity<T>(arg: T): T {</span><br><span class="line"> return arg;</span><br><span class="line">};</span><br><span class="line">let output = identity("MyString");</span><br><span class="line">console.log(output);</span><br></pre></td></tr></table></figure><h2 id="Generic-function"><a href="#Generic-function" class="headerlink" title="Generic function"></a>Generic function</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">function identity<T>(arg: T): T {</span><br><span class="line"> return arg;</span><br><span class="line">}</span><br><span class="line">let output = identity("MyString");</span><br><span class="line">console.log(output);</span><br></pre></td></tr></table></figure><h2 id="Working-with-Generic-Type-Variables"><a href="#Working-with-Generic-Type-Variables" class="headerlink" title="Working with Generic Type Variables"></a>Working with Generic Type Variables</h2><p>我们可以把泛型变量 T 当做类型的一部分使用,而不是整个类型,增加了灵活性</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function loggingIdentity<T>(arg: T[]): T[] {</span><br><span class="line"> console.log(arg.length);</span><br><span class="line"> return arg;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Generic-Types"><a href="#Generic-Types" class="headerlink" title="Generic Types"></a>Generic Types</h2><p>泛型函数的类型与非泛型函数的类型没什么不同,只是有一个类型参数在最前面,像函数声明一样</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function identity<T>(arg: T): T {</span><br><span class="line"> return arg; </span><br><span class="line">}</span><br><span class="line">let myIdentity: <T>(arg: T) => T = identity;</span><br></pre></td></tr></table></figure><p>我们也可以使用不同的参数名,只要在数量上能对应上就可以。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function identity<T>(arg: T): T {</span><br><span class="line"> return arg;</span><br><span class="line">}</span><br><span class="line">let myIdentity: <U>(arg: U) => U = identity;</span><br></pre></td></tr></table></figure><p>我们也可以使用带有调用签名的对象字面量来定义泛型函数</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function identity<T>(arg: T): T {</span><br><span class="line"> return arg;</span><br><span class="line">}</span><br><span class="line">let myIdentity: { <U>(arg: U): U } = identity;</span><br></pre></td></tr></table></figure><p>第一个泛型接口</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">interface GenericIdentityFn {</span><br><span class="line"> <T>(arg: T): T;</span><br><span class="line">}</span><br><span class="line">function identity<T>(arg: T): T {</span><br><span class="line"> return arg; </span><br><span class="line">}</span><br><span class="line">let myIdentity: GenericIdentityFn = identity;</span><br></pre></td></tr></table></figure><p>我们可能想把泛型参数当作整个接口的一个参数</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">interface GenericIdentityFn<T> {</span><br><span class="line"> (arg: T): T;</span><br><span class="line">}</span><br><span class="line">function identity<T>(arg: T): T {</span><br><span class="line"> return arg;</span><br><span class="line">}</span><br><span class="line">let myIdentity: GenericIdentityFn<number> = identity;</span><br></pre></td></tr></table></figure><h2 id="Generic-Classes"><a href="#Generic-Classes" class="headerlink" title="Generic Classes"></a>Generic Classes</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">class GenericNumber<T>{</span><br><span class="line"> zeroValue: T | undefined;</span><br><span class="line"> add: ((x: T, y: T) => T) | undefined;</span><br><span class="line">}</span><br><span class="line">let myGenericNumber = new GenericNumber<number>(); </span><br><span class="line">myGenericNumber.zeroValue = 0; </span><br><span class="line">myGenericNumber.add = function (x, y) { return x + y; }</span><br></pre></td></tr></table></figure><h2 id="Generic-Constraints"><a href="#Generic-Constraints" class="headerlink" title="Generic Constraints"></a>Generic Constraints</h2><p>我们定义一个接口来描述约束条件,创建一个包含 .length 属性的接口,使用这个接口和 extends 关键字来实现约束。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">interface lengthwise {</span><br><span class="line"> length: number;</span><br><span class="line">}</span><br><span class="line">function loggingIdentity<T extends lengthwise>(arg: T): T {</span><br><span class="line"> console.log(arg.length); </span><br><span class="line"> return arg;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="Using-Type-Parameters-in-Generic-Constraints"><a href="#Using-Type-Parameters-in-Generic-Constraints" class="headerlink" title="Using Type Parameters in Generic Constraints"></a>Using Type Parameters in Generic Constraints</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">function getProperty<T, K extends keyof T>(obj: T, key: K) {</span><br><span class="line"> return obj[key];</span><br><span class="line">}</span><br><span class="line">let x = { a: 1, b: 2, c: 3, d: 4 }; </span><br><span class="line">getProperty(x, "a");</span><br></pre></td></tr></table></figure><h3 id="Using-Class-Types-in-Generics"><a href="#Using-Class-Types-in-Generics" class="headerlink" title="Using Class Types in Generics"></a>Using Class Types in Generics</h3><p>在 TypeScript 使用泛型创建工厂函数时,需要引用构造函数的类类型</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">function create<T>(c: { new(): T; }): T {</span><br><span class="line"> return new c();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>A more advanced example</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">class BeeKeeper {</span><br><span class="line"> hasMark: boolean;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">class ZooKeeper {</span><br><span class="line"> nameTag: number;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">class Animal {</span><br><span class="line"> numLegs: number;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">class Bee extends Animal {</span><br><span class="line"> keeper: BeeKeeper;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">class Lion extends Animal {</span><br><span class="line"> keeper: ZooKeeper;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">function createInstance<A extends Animal>(c: new () => A): A {</span><br><span class="line"> return new c();</span><br><span class="line">}</span><br><span class="line">createInstance(Lion).keeper.nameTag; </span><br><span class="line">createInstance(Bee).keeper.hasMark;</span><br></pre></td></tr></table></figure>]]></content:encoded>
<comments>https://qiyanan.com/2019/09/09/TypeScript-Generic/#disqus_thread</comments>
</item>
<item>
<title>TypeScript-Functions</title>
<link>https://qiyanan.com/2019/09/09/TypeScript-Functions/</link>
<guid>https://qiyanan.com/2019/09/09/TypeScript-Functions/</guid>
<pubDate>Mon, 09 Sep 2019 02:53:29 GMT</pubDate>
<description>
<h1 id="Functions"><a href="#Functions" class="headerlink" title="Functions"></a>Functions</h1><p>两种 JavaScript 函数:</p>
<figure class="highl
</description>
<content:encoded><![CDATA[<h1 id="Functions"><a href="#Functions" class="headerlink" title="Functions"></a>Functions</h1><p>两种 JavaScript 函数:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">// 方式一:</span><br><span class="line">function add(x, y) {</span><br><span class="line"> return x + y;</span><br><span class="line">}</span><br><span class="line">let myAdd = function (x, y) { return x + y }; </span><br><span class="line"></span><br><span class="line">// 方式二:</span><br><span class="line">ley z = 100; </span><br><span class="line">function addToZ(x, y) {</span><br><span class="line"> return x + y + z;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Function-Types"><a href="#Function-Types" class="headerlink" title="Function Types"></a>Function Types</h2><h3 id="Typing-the-Types"><a href="#Typing-the-Types" class="headerlink" title="Typing the Types"></a>Typing the Types</h3><p>让我们替上面那个函数添加类型</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function add(x:number, y:number) {</span><br><span class="line"> return x + y;</span><br><span class="line">}</span><br><span class="line">let myAdd = function (x:number, y:number) { return x + y };</span><br></pre></td></tr></table></figure><h3 id="Writing-the-function-type"><a href="#Writing-the-function-type" class="headerlink" title="Writing the function type"></a>Writing the function type</h3><p><code>let myAdd : (x: number, y: number) => number = function (x: number, y: number): number { return x + y; };</code></p><p>我们写参数类型像参数列表一样,给每个采纳数一个名称哥一个类型,这个名字只是为了提供可读性</p><p><code>let myAdd : (baseValue: number, Increment: number) => number = function (x: number, y: number): number { return x + y; };</code></p><h3 id="Inferring-the-types"><a href="#Inferring-the-types" class="headerlink" title="Inferring the types"></a>Inferring the types</h3><p><code>let myAdd = function (x: number, y: number): number { return x + y; };</code></p><p><code>let myAdd: (baseValue: number, Increment: number) => number = function (x, y) { return x + y; };</code></p><h3 id="Optional-and-Default-Parameters"><a href="#Optional-and-Default-Parameters" class="headerlink" title="Optional and Default Parameters"></a>Optional and Default Parameters</h3><p>TypeScript 里的每个函数都是必须的,传递给一个函数的参数个数必须与原函数期望的参数个数一致</p><ol><li>Optional Parameters</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">function buildName(firstName: string, lastName?: string) {</span><br><span class="line"> if(lastName){</span><br><span class="line"> return firstName + "" + lastName;</span><br><span class="line"> }else</span><br><span class="line"> return firstName;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong><em>可选参数必须跟在必选参数后面</em></strong></p><ol start="2"><li>Default parameters</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">function buildName(firstName: string, lastName="Smith") {</span><br><span class="line"> if(lastName){</span><br><span class="line"> return firstName + "" + lastName;</span><br><span class="line"> }else</span><br><span class="line"> return firstName; </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>与普通的可选参数不同,带默认值的参数不需要放在必选参数的后面。<br><strong>如果带默认值的参数出现在必选参数前面,用户必须明确的传入 undefined 值来获得默认值</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">function buildName(firstName="Will", lastName:string) {</span><br><span class="line"></span><br><span class="line"> if(lastName){</span><br><span class="line"> return firstName + "" + lastName;</span><br><span class="line"> }else</span><br><span class="line"> return firstName;</span><br><span class="line">}</span><br><span class="line">let result = buildName(undefined, "Adms")</span><br></pre></td></tr></table></figure><h2 id="Rest-Parameters"><a href="#Rest-Parameters" class="headerlink" title="Rest Parameters"></a>Rest Parameters</h2><p>有时,我们想同时操作多个参数,或者,我们不知道会有多少参数传递进来,在 TypeScript 里,我们可以把所有的参数收集到一个变量里:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function buildName(firstName:string, ...restOfName:string[]){</span><br><span class="line"> return firstName+" "+restOfName.join(" ");</span><br><span class="line">}</span><br><span class="line">let employeeName = buildName("joseph","Samuel","Lucas","MacKinzie");</span><br></pre></td></tr></table></figure><h2 id="this"><a href="#this" class="headerlink" title="this"></a>this</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">let deck = {</span><br><span class="line"> suits: ["hearts", "spades", "clubs", "diamonds"],</span><br><span class="line"> cards: Array(52),</span><br><span class="line"> createCardPicker: function () {</span><br><span class="line"> return function () {</span><br><span class="line"> let pickedCard = Math.floor(Math.random() * 52);</span><br><span class="line"> let pickedSuit = Math.floor(pickedCard / 13);</span><br><span class="line"> return {</span><br><span class="line"> suit: this.suits[pickedSuit], card: pickedCard % 13</span><br><span class="line"> };</span><br><span class="line"> };</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">let cardPicker = deck.createCardPicker();</span><br><span class="line">let pickedCard = cardPicker();</span><br><span class="line">alert( `card: ${pickedCard.card} of ${pickedCard.suit}` );</span><br></pre></td></tr></table></figure><p>可以看到 CreateCardPicker 是个函数,并且它返回一个函数,如股票我们尝试运行这个程序,发现他没有弹出对话框而是报错了,因为 createCarPicker 返回的函数里的 this 设置成了 window 而不是 deck 对象,因为我们只是独立的调用了 cardPicker(),顶级的非方法调用会将 this 视为 window。<br>为了解决这个问题,我们可以在函数被返回时就绑好正确的 this,这样的话,无论之后怎么使用它,都会引用绑定的 deck 对象,我们需要改变函数表达式来使用 ECMAScript 6箭头语法,箭头函数能保存函数时的 this 值,而不是调用时的值。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">let deck = {</span><br><span class="line"> suits: ["hearts", "spades", "clubs", "diamonds"],</span><br><span class="line"> cards: Array(52),</span><br><span class="line"> createCardPicker: function () {</span><br><span class="line"> return () => {</span><br><span class="line"> let pickedCard = Math.floor(Math.random() * 52);</span><br><span class="line"> let pickedSuit = Math.floor(pickedCard / 13);</span><br><span class="line"> return {</span><br><span class="line"> suit: this.suits[pickedSuit], card: pickedCard % 13</span><br><span class="line"> };</span><br><span class="line"> };</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">let cardPicker = deck.createCardPicker();</span><br><span class="line">let pickedCard = cardPicker();</span><br><span class="line">alert( `card: ${pickedCard.card} of ${pickedCard.suit}` );</span><br></pre></td></tr></table></figure><h3 id="this-parameters"><a href="#this-parameters" class="headerlink" title="this parameters"></a>this parameters</h3><p>让我们往例子里添加有一些接口,Card 和 Deck,让类型的重用能够变得清晰简单些</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">interface Card {</span><br><span class="line"> suit: string;</span><br><span class="line"> card: number;</span><br><span class="line">}</span><br><span class="line">interface Deck {</span><br><span class="line"> suits: string[];</span><br><span class="line"> cards: number[];</span><br><span class="line"> createCardPicker(this: Deck): () => Card;</span><br><span class="line">}</span><br><span class="line">let deck = {</span><br><span class="line"> suits: ["hearts", "spades", "clubs", "diamonds"],</span><br><span class="line"> cards: Array(52),</span><br><span class="line"> createCardPicker: function (this: Deck) {</span><br><span class="line"> return () => {</span><br><span class="line"> let pickedCard = Math.floor(Math.random() * 52);</span><br><span class="line"> let pickedSuit = Math.floor(pickedCard / 13);</span><br><span class="line"> return {</span><br><span class="line"> suit: this.suits[pickedSuit], card: pickedCard % 13</span><br><span class="line"> };</span><br><span class="line"> };</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">let cardPicker = deck.createCardPicker();</span><br><span class="line">let pickedCard = cardPicker();</span><br><span class="line">alert( `card: ${pickedCard.card} of ${pickedCard.suit}` );</span><br></pre></td></tr></table></figure><p>现在,TypeScript 知道 createCardPicker 期望在某个 deck 对象上调用,也就是说 this 是 Deck 类型的,而非 any</p><h3 id="this-parameters-in-callbacks"><a href="#this-parameters-in-callbacks" class="headerlink" title="this parameters in callbacks"></a>this parameters in callbacks</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">interface UIElement {</span><br><span class="line"> addClickListener(onclick: (this: void, e: Event) => void): void;</span><br><span class="line">}</span><br><span class="line">class Handler {</span><br><span class="line"> info: string;</span><br><span class="line"> onClickBad(this: Handler, e: Event) {</span><br><span class="line"> console.log('clicked!');</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">let b = new Handler();</span><br><span class="line">uiElement.addClickListener(b.onClickBad);</span><br></pre></td></tr></table></figure><h2 id="Overloads"><a href="#Overloads" class="headerlink" title="Overloads"></a>Overloads</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">let suits = ["hearts", "spades", "clubs", "diamonds"];</span><br><span class="line">function pickedCard(x: { suit: string; card: number }[]): number;</span><br><span class="line">function pickedCard(x: number): { suit: string; card: number; }</span><br><span class="line">function pickedCard(x: any): any {</span><br><span class="line"> if (typeof x == "object") {</span><br><span class="line"> let pickedCard = Math.floor(Math.random() * x % 13);</span><br><span class="line"> return pickedCard;</span><br><span class="line"> } else if (typeof x == "number") {</span><br><span class="line"> let pickedSuit = Math.floor(x / 13);</span><br><span class="line"> return { suit: suits[pickedSuit], card: x % 13 };</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">let myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }]</span><br><span class="line">let pickedCard1 = myDeck[pickedCard(myDeck)];</span><br><span class="line">alert( `card: ${pickedCard1.card} of ${pickedCard1.suit}` );</span><br><span class="line">let pickedCard2 = pickedCard(15);</span><br><span class="line">alert( `card: ${pickedCard2.card} of ${pickedCard2.suit}` );</span><br></pre></td></tr></table></figure>]]></content:encoded>
<comments>https://qiyanan.com/2019/09/09/TypeScript-Functions/#disqus_thread</comments>
</item>
<item>
<title>TypeScript-Class</title>
<link>https://qiyanan.com/2019/09/06/TypeScript-Class/</link>
<guid>https://qiyanan.com/2019/09/06/TypeScript-Class/</guid>
<pubDate>Fri, 06 Sep 2019 09:00:05 GMT</pubDate>
<description>
<h1 id="TypeScript-Class"><a href="#TypeScript-Class" class="headerlink" title="TypeScript-Class"></a>TypeScript-Class</h1><p>下面让我们看一个简单使用类的
</description>
<content:encoded><![CDATA[<h1 id="TypeScript-Class"><a href="#TypeScript-Class" class="headerlink" title="TypeScript-Class"></a>TypeScript-Class</h1><p>下面让我们看一个简单使用类的例子: </p><h2 id="Class"><a href="#Class" class="headerlink" title="Class"></a>Class</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">class Greeter {</span><br><span class="line"> greeting: string;</span><br><span class="line"> constructor(message: string) {</span><br><span class="line"> this.greeting = message;</span><br><span class="line"> }</span><br><span class="line"> greet() {</span><br><span class="line"> return "hello, " + this.greeting;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">let greeter = new Greeter("world");</span><br><span class="line">console.log(greeter.greet());</span><br></pre></td></tr></table></figure><h2 id="Inheritance"><a href="#Inheritance" class="headerlink" title="Inheritance"></a>Inheritance</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">class Animal{</span><br><span class="line"> move(distanceInMeters:number=0){</span><br><span class="line"> console.log( `Animal moved ${distanceInMeters}m` );</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">class Dog extends Animal{</span><br><span class="line"> bark(){</span><br><span class="line"> console.log("woof! woof! ");</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">const dog=new Dog();</span><br><span class="line">dog.bark();</span><br><span class="line">dog.move(10);</span><br><span class="line">dog.bark();</span><br></pre></td></tr></table></figure><p>这个例子展示了最基本的继承功能</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">class Animal {</span><br><span class="line"> name: string;</span><br><span class="line"> constructor(theName: string) {</span><br><span class="line"> this.name = theName;</span><br><span class="line"> }</span><br><span class="line"> move(distanceInMeters: Number = 0) {</span><br><span class="line"> console.log( `${this.name}moved ${distanceInMeters}` );</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">class Snake extends Animal {</span><br><span class="line"> constructor(name: string) {</span><br><span class="line"> super(name);</span><br><span class="line"> }</span><br><span class="line"> move(distanceInMeters = 5) {</span><br><span class="line"> console.log("Slithering...");</span><br><span class="line"> super.move(distanceInMeters);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">class Horse extends Animal {</span><br><span class="line"> constructor(name: string) {</span><br><span class="line"> super(name);</span><br><span class="line"> }</span><br><span class="line"> move(distanceInMeters = 45) {</span><br><span class="line"> console.log("galloping...");</span><br><span class="line"> super.move(distanceInMeters);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">let sam = new Snake("sammy the Python");</span><br><span class="line">let tom: Animal = new Horse("Tommy the palomino");</span><br><span class="line">sam.move();</span><br><span class="line">tom.move(34);</span><br></pre></td></tr></table></figure><h2 id="Public-private-and-protected-修饰符"><a href="#Public-private-and-protected-修饰符" class="headerlink" title="Public, private, and protected 修饰符"></a>Public, private, and protected 修饰符</h2><p><strong><em>在 TypeScript 中,每一个成员默认是 Public </em></strong></p><h3 id="private"><a href="#private" class="headerlink" title="private"></a>private</h3><p>当成员被标记成 private 时,它就不能在声明它的类的外部访问。<br>当比较有 private 成员和 protected 成员的类型时,我们以不同的方式对待它们,如果两个类型中有一个是 private 成员,另一个成员必须有一个来自同一处声明的 private 成员,我们就认为这两个类型是兼容的,上述业适用于 protected 成员</p><h3 id="protected"><a href="#protected" class="headerlink" title="protected"></a>protected</h3><ol><li>一个成员声明为 protected 可以被派生类访问,</li><li>构造函数也可以被声明为 protected,这意味值这个类不能在包含它的类外被实例化,但是能够被继承。</li></ol><h2 id="Readonly-modifier"><a href="#Readonly-modifier" class="headerlink" title="Readonly modifier"></a>Readonly modifier</h2><p>我们可以使用 readonly 关键字将属性设置为只读的,只读属性必须在声明时或构造函数里被初始化。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">class Octopus {</span><br><span class="line"> readonly name: string;</span><br><span class="line"> readonly numberOfLegs: number = 8;</span><br><span class="line"> constructor(theName: string) {</span><br><span class="line"> this.name = theName;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">let dad = new Octopus("man with the 8 strong legs")</span><br></pre></td></tr></table></figure><h2 id="Parameter-properties"><a href="#Parameter-properties" class="headerlink" title="Parameter properties"></a>Parameter properties</h2><p>参数属性允许我们在一个地方创建和初始化成员,</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">class Octopus{</span><br><span class="line"> readonly numberOfLegs:number=8;</span><br><span class="line"> constructor(readonly name:string){}</span><br><span class="line">}</span><br><span class="line">let dad = new Octopus("man with the 8 strong legs")</span><br></pre></td></tr></table></figure><h2 id="Accessors"><a href="#Accessors" class="headerlink" title="Accessors"></a>Accessors</h2><p>TypeScript 支持 getters/setters 作为一种拦截对象成员访问的方法</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">class Employee {</span><br><span class="line"> private _fullName: string;</span><br><span class="line"> get fullName(): string {</span><br><span class="line"> return this._fullName;</span><br><span class="line"> }</span><br><span class="line"> set fullName(newName: string) {</span><br><span class="line"> if (newName && newName.length > fullNameMaxLength) {</span><br><span class="line"> throw new Error("fullName has a max length of " + fullNameMaxLength)''</span><br><span class="line"> }</span><br><span class="line"> this._fullName = newName;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Static-Properties"><a href="#Static-Properties" class="headerlink" title="Static Properties"></a>Static Properties</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">class Grid {</span><br><span class="line"> static origin = { x: 0, y: 0 };</span><br><span class="line"> calculateDistanceFromOrigin(point: { x: number; y: number }) {</span><br><span class="line"> let xDist = (point.x - Grid.origin.x);</span><br><span class="line"> let yDist = (point.y - Grid.origin.y);</span><br><span class="line"> return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;</span><br><span class="line"> }</span><br><span class="line"> constructor(public scale: number) { }</span><br><span class="line">}</span><br><span class="line">let grid1 = new Grid(1.0);</span><br><span class="line">let grid2 = new Grid(5.0);</span><br><span class="line">console.log(grid1.calculateDistanceFromOrigin({ x: 10, y: 10 }));</span><br><span class="line">console.log(grid2.calculateDistanceFromOrigin({ x: 10, y: 100 }));</span><br></pre></td></tr></table></figure><h2 id="Abstract-Classes"><a href="#Abstract-Classes" class="headerlink" title="Abstract Classes"></a>Abstract Classes</h2><p>抽象类被视为其他派生类的基类使用,他们一般不会直接被实例化,不同于接口,抽象类可以包含成员的实现细节,abstract 关键字用于定义抽象类和在抽象类内部定义抽象方法</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">abstract class Animal {</span><br><span class="line"> abstract makeSound(): void;</span><br><span class="line"> move(): void {</span><br><span class="line"> console.log("roaming the earth...";)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Constructor-functions"><a href="#Constructor-functions" class="headerlink" title="Constructor functions"></a>Constructor functions</h2><p>当你在 TypeScript 声明一个类的时候,你实际上同时创建了多个声明,首先就是类的实例类型。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">class Greeter {</span><br><span class="line"> greeting: string;</span><br><span class="line"> constructor(message: string) {</span><br><span class="line"> this.greeting = message;</span><br><span class="line"> }</span><br><span class="line"> greet() {</span><br><span class="line"> return "Hello, " + this.greeting;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">let greeter: Greeter;</span><br><span class="line">greeter = new Greeter("world");</span><br><span class="line">console.log(greeter.greet());</span><br></pre></td></tr></table></figure>]]></content:encoded>
<comments>https://qiyanan.com/2019/09/06/TypeScript-Class/#disqus_thread</comments>
</item>
<item>
<title>TypeScript - Basic Type</title>
<link>https://qiyanan.com/2019/08/09/TypeScript-Basic%20Type/</link>
<guid>https://qiyanan.com/2019/08/09/TypeScript-Basic%20Type/</guid>
<pubDate>Fri, 09 Aug 2019 02:42:17 GMT</pubDate>
<description>
<h1 id="Basic-Types"><a href="#Basic-Types" class="headerlink" title="Basic Types"></a>Basic Types</h1><h2 id="布尔值"><a href="#布尔值" class="he
</description>
<content:encoded><![CDATA[<h1 id="Basic-Types"><a href="#Basic-Types" class="headerlink" title="Basic Types"></a>Basic Types</h1><h2 id="布尔值"><a href="#布尔值" class="headerlink" title="布尔值"></a>布尔值</h2><p><code>let isDone:boolean = false;</code></p><h2 id="数字"><a href="#数字" class="headerlink" title="数字"></a>数字</h2><p>(和JavaScript一样,TypeScript里的所有数字都是浮点型的,这些浮点类型是number)</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">let decLiteral: number = 6;</span><br><span class="line">let hexLiteral: number = 0Xf00d;</span><br><span class="line">let binaryLiteral: number = 0b1010;</span><br><span class="line">let octaliteral: number = 0o744;</span><br></pre></td></tr></table></figure><h2 id="字符串"><a href="#字符串" class="headerlink" title="字符串"></a>字符串</h2><p>(使用单引号或者双引号表示字符串)</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">let name; string = " bob";</span><br><span class="line">name = "smith";</span><br></pre></td></tr></table></figure><p>可以使用模板字符串,也可以定义多行文本和内嵌表达式,这种字符串是被反引号包围( ` ), 并且以$( expr )这种形式嵌入表达式</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">let name: string = `Gene` ;</span><br><span class="line">let age: number = 37;</span><br><span class="line">let sentence: string = `Hello, my name is ${ name }.</span><br><span class="line">I 'll be ${ age+1 } years old next month.`;</span><br></pre></td></tr></table></figure><h2 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h2><p>在元素类型后面接上[], 表示此类型组成的一个数组:</p><p><code>let list: number[] = {1, 2, 3};</code></p><p>使用数据泛型,Array<元素类型></p><p><code>let list: Array< number > = {1, 2, 3};</code></p><h2 id="元组-Tuple"><a href="#元组-Tuple" class="headerlink" title="元组 Tuple"></a>元组 Tuple</h2><p>(允许表示一个已知元素数量和类型的数组,各元素的类型不必相同)</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">//Declare a tuple type</span><br><span class="line">let x: [string , number];</span><br><span class="line">//Initialize</span><br><span class="line">x = ["hello", 10];//OK</span><br><span class="line">//Initialize it incorrectly</span><br><span class="line">x = [10,'hello'];//Error</span><br></pre></td></tr></table></figure><p>当访问一个已知索引的元素,会得到正确的类型:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">console.log( x[0].substr(1));// OK</span><br><span class="line">console.log( x[1].substr(1));// Error,'numbers' does not have 'substr'</span><br></pre></td></tr></table></figure><p><strong><em>当访问一个越界的元素,会使用联合类型替代:(联合类型是高级主题)</em></strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">x[3] = "world"; // OK,字符串可以赋值给(string | sumber)类型</span><br><span class="line">console.log(x[5].toString());//OK,'string' 和'number'都有toString</span><br><span class="line">x[6] =true ;//Error,布尔不是(string | number)类型</span><br></pre></td></tr></table></figure><h2 id="枚举"><a href="#枚举" class="headerlink" title="枚举"></a>枚举</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">enum Color { Red, Green,Blue}</span><br><span class="line">let c: Coloe = Coleo.Green;</span><br></pre></td></tr></table></figure><p>默认情况下,从0开始为元素编号,也可以手动设置</p><h2 id="Any"><a href="#Any" class="headerlink" title="Any"></a>Any</h2><p>(使类型检查器不对这些值检查直接让他们通过编译阶段)</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">let notSure: any = 4; </span><br><span class="line">notSure = "maybe a string instead"; </span><br><span class="line">notSure = false;</span><br></pre></td></tr></table></figure><p><strong>any</strong> 类型是十分有用的,它允许你在编译时可选择的包含或者移除类型检查,你可能认为在其他语言中 <strong>Object</strong> 有类似的作用,然而,<strong>Object</strong>只允许你给它赋任意值,即便它拥有方法,你不能调用。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">let notSure: any = 4;</span><br><span class="line">notSure.ifitExists();//okay, ifitExists might exist at runtime</span><br><span class="line">notSure.toFixed();//Okay, toFixed exists</span><br></pre></td></tr></table></figure><p><img src="/2019/08/09/TypeScript-Basic Type/Any.png" alt="avatar"></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">let prettySure: Object = 4;</span><br><span class="line">prettySure.ToFixed();//Error:Property "toFind" doesn't exist on type 'Object'.</span><br></pre></td></tr></table></figure><p><img src="/2019/08/09/TypeScript-Basic Type/Object.png" alt="avatar"></p><p>如果你只知道一部分数据类型的时候,<strong>any</strong> 类型也是有用的,比如你可能有一个包含了不同数据类型的数组</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">let list: any[] = [1, true, "free"];</span><br><span class="line">list[1] = 100;</span><br></pre></td></tr></table></figure><h2 id="void"><a href="#void" class="headerlink" title="void"></a>void</h2><p>某种程度上来说,void 类型与 any 类型相反,它表示没有任何类型,你通常会看到当一个函数没有返回值的时候,该函数的返回值类型是 void</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">function warnUser(): void {</span><br><span class="line"> console.log("This is my warning message");</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>声明一个 void 类型的变量没有什么大用,应为你只能为它赋予 undefined 和 null:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">let unusable: void = undefined;</span><br><span class="line">let unKnow: void = null;</span><br></pre></td></tr></table></figure><h2 id="Null-and-Underfined"><a href="#Null-and-Underfined" class="headerlink" title="Null and Underfined"></a>Null and Underfined</h2><p>TypeScript 里,undefined 和 null 两者各自有自己的类型分别叫做 undefined 和 null,和 void 相似,他们的本身用处不是很大:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">let u: undefined = undefined;</span><br><span class="line">let n: null = null;</span><br></pre></td></tr></table></figure><p>默认情况下,<strong>null</strong> 和 <strong>undefined</strong> 是所有类型的子类型,这意味着你可以将 null 和 undefined 赋值给任何类型就像 number。<br>然而,你指定了 –strictNullChecks 标记,null 和 undefined 只能赋值给他们各自本身,(其中 undefined 也不能赋值给 void),这就帮助避免了很多常见的问题,也许你想在某处传一个 string 或 null 或 undefined,你可以使用联合类型 string | null | undefined。<br><strong><em>注意:我们鼓励尽可能多的使用 –strictNullChecks</em></strong></p><h2 id="Never"><a href="#Never" class="headerlink" title="Never"></a>Never</h2><p>never 类型表示的是那些永不存在的类型。例如,never 类型是那些总是会抛出异常或者根本就不会有返回值的函数表达式或者箭头函数的返回值类型,当变量被永不为真的类型保护所约束时,该变量可能是 never 类型。</p><p>never 类型是任何类型的子类型,也可以赋值给任何类型,除了 never 本身以外,没有值可以赋值给 never 类型,即便是 any 也不可以赋值给 never。</p><h2 id="Object"><a href="#Object" class="headerlink" title="Object"></a>Object</h2><p>object 表示的是除 number, string, boolean, symbol, null, undefined 的非原始类型,<br>使用 object 类型,就可以更好的表示像 object.create 这样的 API。例如</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">declare function create(o: object | null): void;</span><br><span class="line">create({ prop: 0 });OK</span><br><span class="line">create(null);OK</span><br><span class="line">create(42);//Error</span><br><span class="line">create("string");//Error</span><br><span class="line">create(false);//error</span><br><span class="line">create(undefined);//Error</span><br></pre></td></tr></table></figure><h2 id="Type-assertions"><a href="#Type-assertions" class="headerlink" title="Type assertions"></a>Type assertions</h2><ul><li><p>类型断言有两种形式,第一种是尖括号语法:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">let someValue: any = "this is a string ";</span><br><span class="line">let strLength: number = (<string>someValue).length;</span><br></pre></td></tr></table></figure></li><li><p>as 语法</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">let somevalue: any="this is a string"; </span><br><span class="line">let strLength: number = (someValue as string).length;</span><br></pre></td></tr></table></figure></li></ul><p><strong>当你在 TypeScript 里使用 JSX 时,只有 as 语法断言是被允许的</strong></p>]]></content:encoded>
<comments>https://qiyanan.com/2019/08/09/TypeScript-Basic%20Type/#disqus_thread</comments>
</item>
</channel>
</rss>