文档章节

TypeScript基础入门之JSX(二)

durban
 durban
发布于 2018/10/20 22:17
字数 1263
阅读 20
收藏 0

转发 TypeScript基础入门之JSX(二)

属性类型检查

键入检查属性的第一步是确定元素属性类型。
内在元素和基于价值的元素之间略有不同。

对于内部元素,它是JSX.IntrinsicElements上的属性类型

declare namespace JSX {
  interface IntrinsicElements {
    foo: { bar?: boolean }
  }
}

// element attributes type for 'foo' is '{bar?: boolean}'
<foo bar />;

对于基于价值的元素,它有点复杂。
它由先前确定的元素实例类型上的属性类型确定。
使用哪个属性由JSX.ElementAttributesProperty确定。
它应该用单个属性声明。
然后使用该属性的名称。
从TypeScript 2.8开始,如果未提供JSX.ElementAttributesProperty,则将使用类元素的构造函数或SFC调用的第一个参数的类型。

declare namespace JSX {
  interface ElementAttributesProperty {
    props; // specify the property name to use
  }
}

class MyComponent {
  // specify the property on the element instance type
  props: {
    foo?: string;
  }
}

// element attributes type for 'MyComponent' is '{foo?: string}'
<MyComponent foo="bar" />

元素属性类型用于键入检查JSX中的属性。
支持可选和必需的属性。

declare namespace JSX {
  interface IntrinsicElements {
    foo: { requiredProp: string; optionalProp?: number }
  }
}

<foo requiredProp="bar" />; // ok
<foo requiredProp="bar" optionalProp={0} />; // ok
<foo />; // error, requiredProp is missing
<foo requiredProp={0} />; // error, requiredProp should be a string
<foo requiredProp="bar" unknownProp />; // error, unknownProp does not exist
<foo requiredProp="bar" some-unknown-prop />; // ok, because 'some-unknown-prop' is not a valid identifier

注意:如果属性名称不是有效的JS标识符(如data-*属性),则如果在元素属性类型中找不到它,则不会将其视为错误。

此外,JSX.IntrinsicAttributes接口可用于指定JSX框架使用的额外属性,这些属性通常不被组件的props或参数使用 - 例如React中的键。
进一步说,通用JSX.IntrinsicClassAttributes <T>类型也可用于为类组件(而不是SFC)指定相同类型的额外属性。
在此类型中,泛型参数对应于类实例类型。
在React中,这用于允许类型为Ref <T>的ref属性。
一般来说,这些接口上的所有属性都应该是可选的,除非您打算让JSX框架的用户需要在每个标记上提供一些属性。
扩展操作符也是有效的:

var props = { requiredProp: "bar" };
<foo {...props} />; // ok

var badProps = {};
<foo {...badProps} />; // error

子类型检查

在TypeScript 2.3中,TS引入了子类型检查。
children是元素属性类型中的特殊属性,其中子JSXExpressions被插入到属性中。
类似于TS使用JSX.ElementAttributesProperty来确定props的名称,TS使用JSX.ElementChildrenAttribute来确定这些props中的子项名称。
应使用单个属性声明JSX.ElementChildrenAttribute。

declare namespace JSX {
  interface ElementChildrenAttribute {
    children: {};  // specify children name to use
  }
}
<div>
  <h1>Hello</h1>
</div>;

<div>
  <h1>Hello</h1>
  World
</div>;

const CustomComp = (props) => <div>props.children</div>
<CustomComp>
  <div>Hello World</div>
  {"This is just a JS expression..." + 1000}
</CustomComp>


您可以像任何其他属性一样指定子类型。
这将覆盖默认类型,例如React typings(如果您使用它们)。

interface PropsType {
  children: JSX.Element
  name: string
}

class Component extends React.Component<PropsType, {}> {
  render() {
    return (
      <h2>
        {this.props.children}
      </h2>
    )
  }
}

// OK
<Component>
  <h1>Hello World</h1>
</Component>

// Error: children is of type JSX.Element not array of JSX.Element
<Component>
  <h1>Hello World</h1>
  <h2>Hello World</h2>
</Component>

// Error: children is of type JSX.Element not array of JSX.Element or string.
<Component>
  <h1>Hello</h1>
  World
</Component>

JSX结果类型

默认情况下,JSX表达式的结果键入为any。您可以通过指定JSX.Element接口来自定义类型。但是,无法从此接口检索有关JSX的元素,属性或子级的类型信息。这是一个黑盒子。

嵌入表达式

JSX允许您通过用大括号({})包围表达式来在标记之间嵌入表达式。

var a = <div>
  {["foo", "bar"].map(i => <span>{i / 2}</span>)}
</div>

上面的代码将导致错误,因为您不能将字符串除以数字。
使用preserve选项时,输出如下所示:

var a = <div>
  {["foo", "bar"].map(function (i) { return <span>{i / 2}</span>; })}
</div>

React整合

要将JSX与React一起使用,您应该使用React类型。
这些类型适当地定义了JSX名称空间以与React一起使用。

/// <reference path="react.d.ts" />

interface Props {
  foo: string;
}

class MyComponent extends React.Component<Props, {}> {
  render() {
    return <span>{this.props.foo}</span>
  }
}

<MyComponent foo="bar" />; // ok
<MyComponent foo={0} />; // error

工厂函数

jsx:react编译器选项使用的确切工厂函数是可配置的。
可以使用jsxFactory命令行选项或内联@jsx注释编译指示来设置它以基于每个文件进行设置。
例如,如果将jsxFactory设置为createElement,则<div />将作为createElement("div")而不是React.createElement("div")来编译。

注释pragma版本可以像这样使用(在TypeScript 2.8中):

import preact = require("preact");
/* @jsx preact.h */
const x = <div />;

编译为

const preact = require("preact");
const x = preact.h("div", null);

选择的工厂也将影响JSX命名空间的查找位置(用于类型检查信息),然后再回退到全局命名空间。
如果工厂定义为React.createElement(默认值),编译器将在检查全局JSX之前检查React.JSX。
如果工厂定义为h,它将在全局JSX之前检查h.JSX。

© 著作权归作者所有

共有 人打赏支持
durban
粉丝 99
博文 568
码字总数 184197
作品 0
崇明
后端工程师
私信 提问
TypeScript系列1-简介及版本新特性

简介 随着PC端快速向移动端迁移,移动(体验)优先的概念也越来越响。由于ReactJS目前移动端仅仅支持iOS,因此移动端Web开发框架只能选择: AngularJS/Angula2 + Ionic框架 + Cordova。想要学...

一配
2015/08/15
0
0
TypeScript基础入门 - 函数 - this(二)

转载 TypeScript基础入门 - 函数 - this(二) 项目实践仓库 为了保证后面的学习演示需要安装下ts-node,这样后面的每个操作都能直接运行看到输出的结果。 后面自己在练习的时候可以这样使用 ...

durban
2018/08/19
0
0
TypeScript 3.0 新功能介绍(二)

转载 TypeScript 3.0 新功能介绍(二) TypeScript 3.0 新功能介绍(二) New unknown top type TypeScript 3.0引入了一种新的顶级类型unknown。 unknown是任何类型安全的对应物。 任何东西都...

durban
2018/09/05
0
0
TypeScript基础入门之JSX(一)

转发 TypeScript基础入门之JSX(一) 介绍 JSX是一种可嵌入的类似XML的语法。 它旨在转换为有效的JavaScript,尽管该转换的语义是特定于实现的。 JSX在React框架中越来越受欢迎,但此后也看到了...

durban
2018/10/19
0
0
TypeScript 3.0 正式发布:引入“项目引用”新概念

北京时间7月31日,微软宣布推出 TypeScript 3.0 正式版。 TypeScript 3.0 是一个新的里程碑。官方表示,尽管版本号是一个大变化,但 3.0 版本几乎没有破坏性的变更(这意味着我们可以很轻松地...

局长
2018/07/31
6.2K
32

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 舔狗是没有好下场的

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @我没有抓狂 :#今天听什么# #今天听这个# 分享 Nirvana 的歌曲《Smells Like Teen Spi...》 《Smells Like Teen Spi...》- Nirvana 手机党少...

小小编辑
40分钟前
9
2
Linux Wireshark普通用户启动使用方案

当系统安装好Wireshark后请正常启动是否可以进行正常使用,如果不行请参考下列指导 向系统添加一个用户组 sudo groupadd wireshark //如提示此组存在可跳过 将指定用户添加到这个组中 sudo...

CHONGCHEN
今天
2
0
CSS 选择器参考手册

CSS 选择器参考手册 选择器 描述 [attribute] 用于选取带有指定属性的元素。 [attribute=value] 用于选取带有指定属性和值的元素。 [attribute~=value] 用于选取属性值中包含指定词汇的元素。...

Jack088
今天
2
0
数据库篇一

数据库篇 第1章 数据库介绍 1.1 数据库概述  什么是数据库(DB:DataBase) 数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据...

stars永恒
今天
5
0
Intellij IDEA中设置了jsp页面,但是在访问页面时却提示404

在Intellij IDEA中设置了spring boot的jsp页面,但是在访问时,却出现404,Not Found,经过查找资料后解决,步骤如下: 在Run/Debug Configurations面板中设置该程序的Working Directory选项...

uknow8692
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部