GithubHelp home page GithubHelp logo

blog's People

Contributors

techird avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blog's Issues

[翻译] TypeScript 大法好!

原文地址:https://medium.com/@vivainio/typescript-is-pretty-good-d8fecf80ea0c

概览:为什么说跟 ES6 比起来,TypeScript 更好呢?

好高兴,现在前端社区开始普遍接受转译的做法了(即把各种语法转换成 JS 执行)。虽然还是有部分 ES5 的死忠粉,但他们之中,有绝大部分在一旦在心里接受了 Crockford 的信仰之后,也会忘掉过往固执的经验并且开始转军接受。

大家都知道 ES6 相当牛逼。然而无论怎么牛逼的 ES6 始终有一样东西是给不了你的,那就是帮你检查你的代码是否正确——前人把这个叫做「汇编」或「类型检查」。打个比方,你在第 12 行实例化了类 Foo 的一个对象,ES6 在 13 行就会忘记提醒您这个对象有一个 bar() 方法。在 ES6 的规范下,你导入了你明确知道里面有什么的模块没有用,就是你明确暴露了想要暴露的变量也没有用。

一些代码检查工具可以帮你做一些弱弱的检查,但是它们一般也只是提示一下你该用单引号还是双引号(显然现在单引号比较受欢迎,虽然这是和祖先们写字符串的方法是相悖的)或者是提示你文件尾部缺少了一个空行。这种感觉就像用正则来解析 XML 树一样——一些看起来也挺正常的事儿,但是就是觉得哪儿不对劲。

TypeScript 的主张做的低调又有礼貌;但是你无法估计它们在技术主张上领先了 ES6 规范有多少年(函数式编程的程序员多年来一直处于养尊处优的状态,他们毫不在乎 ES6 跟 C#、Java 比起来就是毫无静态类型的概念)。TypeScript 也会指出 ES6 是很大的进步,但是同时指出,如果你进一步尝试一下 TypeScript 的一些小玩意的话,你会在工具化上面得到一些好处。

理性的工程师不可避免会因为下述原因而对 TypeScript 心存疑虑:

  • 这是未来的大势吗?如果我们选择 TypeScript,项目会不会被边缘化?
  • 如果使用的过程中碰到了什么跨不过去的坎怎么办?如果选择了之后,我们要承受到其设计不合理的恶果怎么办?

对于第一点,早些时候,我确实怀疑 TypeScript 是否能在社区势头大好的 CoffeeScript 上吸引到开发者。现在我在这谈笑风生,但是在 2012 年 TypeScript 刚发布那回,这个担忧并非毫无道理。当 TypeScript 1.5 发布(2015年春发布的 alpha 版)并且和 ES6 对齐后,这种担忧就释然了,就连 Angular 2 也从之前基于 traceur 的 AtScript 玩具转换到 TypeScript 的大阵营中。

对于第二点呢?TypeScript 到底「行不行」?

显然,可选强类型的特性可以让你慢慢的加上类型;应用中还没「准备好」的部分可以先不用加上类型,你的编译器也不会呜呜叫。我个人所见是,你慢慢把类型加上的时候,并不会被提示一些无法预料的问题;通常来说,你反而会抓出之前代码中还没被发现的 BUG。尽管你在你使用的类型定义文件有问题,你也可以转换成「any」类型,然后给 DefinitelyTyped 报告 bug 之后继续你的工作。

基本上,TypeScript 的类型系统想的很通透。它压根不是那种 18 岁的同学上传到 npm 的爱好项目可比的。它在付费项目上使用,人们的生计仰赖于它的稳定发布,所以它有微软付费的工程师进行质量保证以及代码评审。

TypeScript 能和 Flow 竞争吗(FaceBook 的一个类型推导引擎)?我们来探讨下最近 TypeScript 和 Flow 无处不在的争论:

  • Flow 的卖点是使用全局的类型推导,而不是基于你的严格类型定义。然而现在并没有其他语言走到这一步,Hindley-Milner(或类似的)类型推导只能在某些函数式编程语言中作为严格类型定义的附属;你还是需要在你 API 的关键位置上定义你的类型,然后类型推导才能玩起来。
  • TypeScript 在 Node 上托管;Flow 只是一个用于广泛分析 FaceBook 代码库的 unix 工具。你有可能也有可能不在 FaceBook 工作,但是通常情况下你都不在。

这里还有一个对 TypeScript 很不合理,但很重要的偏见——TypeScript 是微软搞的,微软是搞 Windows 的,而 Windows 很糟糕。

TypeScript,是基于 Node 构建的,显然是一个跨平台的项目。微软还在 Visual Studio Code 上花了很大精力,目的是为了给 TypeScript 有一流的、顶级的编辑体验(甚至超越 Windows 平台的 Visual Studio)。他们最近的开发团队已经基于 MIT License 开源发布了他们最大的工程成就(CoreCLR等)。这极有可能是他们在 2015 年及以后最为看重的事情。

毕竟,比 TypeScript 糟糕的多了去了,赌一把绝不吃亏。

补充:直接说 TypeScript 任何时候都是最佳选择也不恰当。如果你是「冲锋枪」,你应该对转译的使用没什么怨言;同样的,如果你只是做一些快速小巧的项目,可维护性和重构能力也不是你首要考虑的。

[翻译] TypeScript 和 JSX 搞基的事

之前的一篇翻译安利了一下 TypeScript,今天再给大家翻译一篇 TypeScript 和 JSX 结合使用的安利文。
原文地址:http://www.jbrantly.com/typescript-and-jsx/

对 JSX 的支持已经在 TypeScript 官方落地了!非常感谢 Ryan CavanaughFrançois de Campredon 的大力推动。在这篇文章中,笔者打算跟大家探索一下如何把 JSX 和 TypeScript 的第一特性——静态类型检查完美结合使用。

发展历史

当我们开始在 AssureSign 项目中实验性地使用 React 的时候,也开始在使用 TypeScript 了。然而当我们碰到 JSX 的时候,一道石墙突然在我们面前挡道。在 Github 中已经有一个历史悠久的 Issue 去反映这个问题,然而一直没有得出实质性的解决方案,或者干脆让你“不要使用 JSX”了。这对我来说不可接受,所以我用了一点黑魔法来解决这个问题。虽然可以玩起来,但这个方法太挫了,并且没有类型检查。François de Campredon 后来创建了一个 jsx-typescript 的项目来证明其实 TypeScript 是可以支持 JSX 的。然后,很突然,会得到 TypeScript 官方支持的消息不胫而走。三个月后,它就真的支持了。

安装

目前 JSX 还没有稳定版本,所以你需要去拉取最新代码。
JSX 已经在 TypeScript 1.6 以上版本支持。

$ npm install typescript

基础使用

使用 JSX 之前,你需要做两件事情:

  1. 文件使用 .tsx 作为扩展名
  2. 开启 TypeScript 的 jsx 选项

TypeScript 发布了两种 JSX 的工作模式:preserve 模式和 react 模式。这两个模式只影响编译策略。preserve 模式会保留 JSX 文件,以便日后进一步被 babel 使用,输出的文件是 .jsx 格式的。而 react 模式则会直接编译成 React.createElement,在使用之前就不需要再做 JSX 转换了,输出的文件是 .js 格式的。

模式 输入 输出
preserve <div/> <div/>
react <div/> React.createElement("div")

你可以在命令行中使用 --jsx 参数或者在 tsconfig.json 中指定工作模式。

注意,编译生成的代码中,React 关键字是硬编码的,所以要保证全局变量中的 React 可用,并且 R 是大写的,react 就不行了。

as 运算符

由于 TypeScript 使用尖括号做类型声明,那么在编译的时候,类型声明会和 JSX 的语法冲突。比如以下代码:

var foo1 = <foo>bar
</foo>

这个代码是准备创建一个 JSX 元素,还是想要声明 bar 变量是 foo 类型的?为了让这个问题简化,.tsx 文件里不支持尖括号类型声明语法。所以如果上面的代码是在 .tsx 文件里的话,表示的是创建了一个 JSX 元素,而如果在 .ts 文件里,就会报错。为了弥补 .tsx 文件中类型声明语法的缺失,添加了一个新的类型声明操作符:as

var foo1 = bar as foo;

as 操作符在 .ts 文件和 .tsx 文件中都是可用的。

类型检查

要是没有类型检查,JSX 和 TypeScript 搞基有什么意义?多亏有了完整的类型检查,世界变得精彩纷呈。

首先,要区别内置元素和自定义元素。给定一个 JSX 表达式 <expr />,这个 expr 到底该对应环境里的一个内置元素(比如 DOM 环境下的 div 或者 span)还是应该对应一个自己写的自定义组件?区分这单很重要,因为:

  1. 对于 React 来说,内置元素会编译成字符串,比如 React.createComponent('div'),而自定义元素则不是:React.createElement(MyComponent)
  2. 传递给 JSX 标签的属性类型的查找方式是不同的。内置元素支持的属性应该是内置的,而自定义组件的属性取决于 props 的定义。

对于这两者,TypeScript 和 React 使用同样的区分方式:内置元素的标签以小写字母开头,自定义元素的标签使用大写字母开头。

内置元素

内置元素会在接口 JSX.InterinsicElements 中定义。默认情况下,如果这个接口并没有定义,那么所有的内置元素都不会进行类型检查。然而,如果你定义了这个接口,那么内置元素将会使用在接口属性中定义的类型。

declare module JSX {  
    interface IntrinsicElements {
        foo: any
    }
}

<foo />; // ok  
<bar />; // error  

在上述示例中,foo 可以通过类型检查但是 bar 不行。因为 bar 在内置元素接口属性中没有定义。

注意:你也可以在 JSX.IntrinsicElements 接口中定义一个字符串索引器来匹配任意的内置元素

笔者注:JSX.IntrinsicElements 在 Dom 环境中的定义已经在 React 的 DefinitelyTyped 中描述好了。React 环境下可直接使用。

自定义元素

自定义元素可以简单地通过标识符来查找到。

import MyComponent = require('./myComponent');

<MyComponent />; // ok  
<SomeOtherComponent />; // error  

我们是可以限制自定义组件的类型的。然而,为了说明白,我们先要介绍两个概念:_组件类类型(Element Class Type)和_组件实例类型(Element Instance Type)

组件类类型很简单,对于 <Expr> 组件,其类类型就是 Expr 的类型。所以在上面的例子中,如果 MyCompoent 是一个 ES6 的类,那么 <MyComponent> 的类类型就是这个类的类型。如果 MyComponent 是一个工厂方法,那么 <MyCompoent> 的类类型就是这个方法的类型。

一旦元素类类型确定了,元素的实例类型就由类的调用签名和构造签名共同决定。在看上述例子,如果 MyComponent 是一个 ES6 的类,那么实例类型就是这个类的实例的类型,如果是个工厂方法,实例类型则是这个方法的返回值。是不是有点绕?我们来看看下面这个例子:

class MyComponent {  
  render() {}
}

// 使用构造函数
var myComponent = new MyComponent();

// 组件类类型 => MyComponent
// 元素实例类型 => { render: () => void }

function MyFactoryFunction() {  
  return { 
    render: () => {
    } 
  }
}

// 使用工厂方法调用
var myComponent = MyFactoryFunction();

// 组件类类型 => MyFactoryFunction
// 组件实例类型 => { render: () => void }

现在组件实例类型是一个有趣的类型,它要求满足 JSX.ElementClass 的接口,否则将会报错。默认情况下,JSX.ElementClass 就是 {},不过我们是可以人为增加限制。

declare module JSX {  
  interface ElementClass {
    render: any;
  }
}

class MyComponent {  
  render() {}
}
function MyFactoryFunction() {  
  return { render: () => {} }
}

<MyComponent />; // ok  
<MyFactoryFunction />; // ok

class NotAValidComponent {}  
function NotAValidFactoryFunction() {  
    return {};
}

<NotAValidComponent />; // error  
<NotAValidFactoryFunction />; // error  

译者注:JSX.ElementClass 同样在 React 的 DefinitelyTyped 中定义好了,大家通过 tsd 或者 nuget 可以下载下来使用

属性类型检查

做属性的类型检查,第一步就是要确定_元素属性类型_。对于内置元素和自定义元素,确定方式有一些区别。

对于内置组件,组件属性类型就是 JSX.IntrinsicElements 上的属性类型。

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

// `foo` 的元素属性类型是 `{bar?: boolean}`
<foo bar />;  

对于自定义组件,情况复杂一点点。它的类型是之前讨论的_组件实例类型_的一个属性决定的。你问我是哪个属性?哈哈,你可以自己决定!在 JSX.ElementAttributesProperty 上定义唯一一个属性,这个属性就是决定自定义组件属性类型的属性。(译者:好绕,还是看示例)

declare module JSX {  
  interface ElementAttributesProperty {
    props; // 指定使用哪个属性名称
  }
}

class MyComponent {  
  // 在元素实例类型上定义这个属性
  props: {
    foo?: string;
  }
}

// `MyComponent` 的元素属性类型就是 `{foo?: string}`
<MyComponent foo="bar" />  

上面的例子可以明显看到,元素属性类型就是用于对 JAX 的元素做类型检查的。支持可选和必选属性。

declare module 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-_ 属性),那么这个属性在进行类型检查的时候不会认为是错误,而是直接跳过。*

属性集也是支持的:

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

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

JSX 的类型

好了,现在我们可以写 JSX 并且有了元素和属性的类型检查,但是 JSX 本身的类型是什么呢?默认来说,JSX 的类型是 any。你可以通过 JSX.Element 接口自定义这个类型。然而,我们从这个接口是不可能知道元素、元素的属性或者子节点的类型信息的。这是个黑盒。

内嵌 TypeScript

JSX 在 Javascript 里允许通过花括号 { } 内嵌 JavaScript 代码。JSX 在 TypeScript 里同样允许你这样做,只不过是内嵌 TypeScript 代码。这就意味着这些 JSX 内嵌的 TypeScript 代码同样支持转译功能以及类型检查。

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 集成

TypeScript 对 JSX 的支持的设计是不考虑其使用方式的。然而,React 始终是主要的使用方。我年初做过一个关于集成 React 和 TypeScript 的演讲。很多观点如今依然适用。React 的 DefiniteTyped 仓库的最近更新中集成了 JSX.IntrinsicElementsJSX.ElementAttributeProperty 的概念。

/// <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  

更多资源

这篇文章中的很多信息都来自 TypeScript 的 Issue #3203。不过,这个讨论已经持续了很长时间并且扩散到很多个地方。我调了几个个人认为值得深挖的:

译者注:转载本文请保留出处:#3

订正

”TypeScript 也会指出 ES6 是很大的进步,大事同时指出,如果你进一步尝试一下 TypeScript 的一些小玩意的话,你会在工具化上面得到一些好处。“

大事==>但是

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.