Skip to content

Commit

Permalink
Add more zh translation
Browse files Browse the repository at this point in the history
  • Loading branch information
Kingwl committed Feb 18, 2020
1 parent 350587c commit e5b0135
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 147 deletions.
@@ -1,8 +1,6 @@
// There are two main tools to declare the shape of an
// object: interfaces and type aliases.
//
// They are very similar, and for the most common cases
// act the same.
// 声明一个对象的类型时,有两个主要的工具:接口(interface)和类型别名(type aliases)。
//
// 他们非常相似,并且在大多数情况下是相同的。

type BirdType = {
wings: 2;
Expand All @@ -15,14 +13,13 @@ interface BirdInterface {
const bird1: BirdType = { wings: 2 };
const bird2: BirdInterface = { wings: 2 };

// Because TypeScript is a structural type system,
// it's possible to intermix their use too.
// 因为 TypeScript 有着结构化类型系统。
// 我们也可以混合使用他们。

const bird3: BirdInterface = bird1;

// They both support extending other interfaces and types.
// Type aliases do this via intersection types, while
// interfaces have a keyword.
// 他们都支持扩展另一个些接口或类型。
// 类型别名通过并集类型来实现,接口通过 extends 关键字。

type Owl = { nocturnal: true } & BirdType;
type Robin = { nocturnal: false } & BirdInterface;
Expand All @@ -39,19 +36,15 @@ interface Chicken extends BirdInterface {
let owl: Owl = { wings: 2, nocturnal: true };
let chicken: Chicken = { wings: 2, colourful: false, flies: false };

// That said, we recommend you use interfaces over type
// aliases. Specifically, because you will get better error
// messages. If you hover over the following errors, you can
// see how TypeScript can provide terser and more focused
// messages when working with interfaces like Chicken.
// 也就是说,我们建议您使用接口而不是类型别名,因为你可以在接口中获得更好的错误提示。
// 如果你将鼠标悬停在下面的错误上,你会看到在使用接口(例如 Chicken)时,
// TypeScript 会提供更简洁的提示信息。

owl = chicken;
chicken = owl;

// One major difference between type aliases vs interfaces
// are that interfaces are open and type aliases are closed.
// This means you can extend an interface by declaring it
// a second time.
// 一个接口和类型别名的主要区别是,接口是开放的,类型别名是封闭的。
// 这意味着你可以你可以通过多次声明同一个接口来扩展它。

interface Kitten {
purrs: boolean;
Expand All @@ -61,8 +54,7 @@ interface Kitten {
colour: string;
}

// In the other case a type cannot be changed outside of
// it's declaration.
// 与此同时,类型别名不可以在外部变更它的声明。

type Puppy = {
color: string;
Expand All @@ -72,12 +64,9 @@ type Puppy = {
toys: number;
};

// Depending on your goals, this difference could be a
// positive or a negative. However for publicly exposed
// types, it's a better call to make them an interface.
// 基于你不同的目的,这个区别可以是证明的也可以是负面的。
// 一般来说,对于公开的需要暴露的类型,将他们作为接口是更好的选择。

// One of the best resources for seeing all of the edge
// cases around types vs interfaces, this stack overflow
// thread is a good place to start:
// 要查看接口和类型定义之间所有边际条件,下面的 stackoverflow 讨论是最好的资源之一:

// https://stackoverflow.com/questions/37233735/typescript-interfaces-vs-types/52682220#52682220
@@ -1,44 +1,34 @@
//// {compiler: { strictFunctionTypes: false } }

// Without a background in type theory, you're unlikely
// to be familiar with the idea of a type system being "sound".
// 如果您没有类型理论方面的背景知识,您可能不太了解
// 类型系统是 “健全的” 这个概念。

// Soundness is the idea that the compiler can make guarantees
// about the type a value has at runtime, and not just
// during compilation. This is normal for most programming
// languages that are built with types from day one.
// 健全性是指编译器可以使值不仅在编译时,还可以在运行时具有预期的类型。
// 这对于大多数从一开始就具有类型的编程语言来说是很正常的。

// Building a type system which models a language which has
// existed for a few decades however becomes about making
// decisions with trade-offs on three qualities: Simplicity,
// Usability and Soundness.
// 要对于一个已经存在了几十年的语言建立一个类型系统,就需要对三个质量维度进行
// 权衡和取舍:简单性,可用性和健全性。

// With TypeScript's goal of being able to support all JavaScript
// code, the language tends towards simplicity and usability
// when presented with ways to add types to JavaScript.
// TypeScript 的目标是支持所有的 JavaScript 代码,
// 且 为 JavaScript 添加类型支持时,语言趋向于简单易用。

// Let's look at a few cases where TypeScript is provably
// not sound, to understand what those trade-offs would look
// like otherwise.
// 让我们看一些让 TypeScript 看起来没那么健全的例子,
// 并且去理解这些权衡和取舍是什么样子。

// Type Assertions
// 类型断言(Type Assertions

const usersAge = ("23" as any) as number;

// TypeScript will let you use type assertions to override
// the inference to something which is quite wrong. Using
// type assertions is a way of telling TypeScript you know
// best, and TypeScript will try to let you get on with it.
// TypeScript 允许您使用类型断言来重写一些可能错误的类型推断。
// 使用类型断言代表告诉 TypeScript 您知道最正确的信息,
// 并且 TypeScript 将会尝试让您继续使用它。

// Languages which are sound would occasionally use runtime checks
// to ensure that the data matches what your types say - but
// TypeScript aims to have no type-aware runtime impact on
// your transpiled code.
// 健全性比较好的语言有时会使用运行时检查来确保数据与您的类型匹配。
// 但是 TypeScript 旨在不对编译后的代码产生类型感知的运行时的影响。

// Function Parameter Bi-variance
// 函数参数双变

// Params for a function support redefining the parameter
// to be a subtype of the original declaration.
// 函数的参数支持将参数重新定义为原始类型声明的子类型。

interface InputEvent {
timestamp: number;
Expand All @@ -52,66 +42,59 @@ interface KeyboardInputEvent extends InputEvent {
}

function listenForEvent(eventType: "keyboard" | "mouse",
handler: (event: InputEvent) => void) {}
handler: (event: InputEvent) => void) { }

// You can re-declare the parameter type to be a subtype of
// the declaration. Above, handler expected a type InputEvent
// but in the below usage examples - TypeScript accepts
// a type which has additional properties.
// 我们可以将参数的类型重新声明为它定义的子类型。
// 上例中 handler 预期为一个 'InputEvent' 类型,但是在后面
// 使用的例子中,TypeScript 接受附加了新属性的类型。

listenForEvent("keyboard", (event: KeyboardInputEvent) => {});
listenForEvent("mouse", (event: MouseInputEvent) => {});
listenForEvent("keyboard", (event: KeyboardInputEvent) => { });
listenForEvent("mouse", (event: MouseInputEvent) => { });

// This can go all the way back to the smallest common type:
// 而这个可以一直回溯到最小的公共类型:

listenForEvent("mouse", (event: {}) => {});
listenForEvent("mouse", (event: {}) => { });

// But no further:
// 但没有更进一步。

listenForEvent("mouse", (event: string) => {});
listenForEvent("mouse", (event: string) => { });

// This covers the real-world pattern of event listener
// in JavaScript, at the expense of having being sound.
// 这覆盖了实际环境中 JavaScript 事件监听器的模式,但是会牺牲一些健全性。

// TypeScript can raise an error when this happens via
// `strictFunctionTypes`. Or, you could work around this
// particular case with function overloads,
// see: example:typing-functions
// 在 'strictFunctionTypes' 选项开启时,TypeScript 可以对此抛出一些异常,
// 或者您可以通过函数重载来解决这个特殊情况。
// 具体可以看 example:typing-functions

// Void special casing

// Parameter Discarding

// To learn about special cases with function parameters
// see example:structural-typing
// 查看 example:structural-typing 以了解更多函数参数的特殊例子。

// Rest Parameters
// 剩余参数

// Rest parameters are assumed to all be optional, this means
// TypeScript will not have a way to enforce the number of
// parameters available to a callback.
// 剩余参数均被推断为可选参数,这意味着 TypeScript 将无法确保
// 用于回调的参数的数量。

function getRandomNumbers(count: number,
callback: (...args: number[]) => void) {}
callback: (...args: number[]) => void) { }

getRandomNumbers(2, (first, second) => console.log([first, second]));
getRandomNumbers(400, first => console.log(first));

// Void Functions Can Match to a Function With a Return Value
// 空返回值函数可以匹配具有返回值的函数

// A function which returns a void function, can accept a
// function which takes any other type.
// 一个返回空的函数,可以接受一个返回其他类型的函数。

const getPI = () => 3.14;

function runFunction (func: () => void) {
function runFunction(func: () => void) {
func();
}

runFunction(getPI);

// For more information on the places where soundness of the
// type system is compromised, see:
// 要了解更多关于类型系统健全性取舍的内容,可以查看:

// https://github.com/Microsoft/TypeScript/wiki/FAQ#type-system-behavior
// https://github.com/Microsoft/TypeScript/issues/9825
Expand Down
@@ -1,13 +1,10 @@
// TypeScript is a Structural Type System. A structural type
// system means that when comparing types, TypeScript only
// takes into account the members on the type.
// TypeScript 是结构化类型系统,结构化类型系统意味着
// 在比较类型时,TypeScript 仅考虑类型上的成员。

// This is in contrast to nominal type systems, where you
// could create two types but could not assign them to each
// other. See example:nominal-typing
// 这与标称类型系统可以创建两种类型,但不能将他们互相赋值的行为不同。
// 查看 example:nominal-typing 以了解更多.

// For example, these two interfaces are completely
// transferrable in a structural type system:
// 例如,如下两个接口在结构化类型系统中,完全可以互相转移。

interface Ball { diameter: number; }
interface Sphere { diameter: number; }
Expand All @@ -18,9 +15,8 @@ let sphere: Sphere = { diameter: 20 };
sphere = ball;
ball = sphere;

// If we add in a type which structurally contains all of
// the members of Ball and Sphere, then it also can be
// set to be a ball or sphere.
// 如果我们添加了一个包含所有 Ball 和 Sphere 类型成员的类型,
// 那么它也可以赋值给 ball 或 sphere。

interface Tube {
diameter: number;
Expand All @@ -32,16 +28,13 @@ let tube: Tube = { diameter: 12, length: 3 };
tube = ball;
ball = tube;

// Because a ball does not have a length, then it cannot be
// assigned to the tube variable. However, all of the members
// of Ball are inside tube, and so it can be assigned.
// 因为 ball 没有 length 属性,所以它不可以被赋值给 tube 变量。
// 然而 tube 包含所有 Ball 的成员,所以 tube 可以被赋值给 ball。

// TypeScript is comparing each member in the type against
// each other to verify their equality.
// TypeScript 将类型中的每个成员进行比较,以验证他们的相等性。

// A function is an object in JavaScript and it is compared
// in a similar fashion. With one useful extra trick around
// the params:
// JavaScript中,一个函数是一个对象,并且他们以类似的方式比较。
// 一个参数的额外技巧:

let createBall = (diameter: number) => ({ diameter });
let createSphere = (diameter: number, useInches: boolean) => {
Expand All @@ -51,31 +44,27 @@ let createSphere = (diameter: number, useInches: boolean) => {
createSphere = createBall;
createBall = createSphere;

// TypeScript will allow (number) to equal (number, boolean)
// in the parameters, but not (number, boolean) -> (number)
// TypeScript 认为 (number) (number, boolean) 在参数中相等,
// 但是不认为 (number, boolean) (number) 相等。

// TypeScript will discard the boolean in the first assignment
// because it's very common for JavaScript code to skip passing
// params when they're not needed.
// TypeScript 将丢弃在第一个赋值中的 boolean 参数。
// 因为这是一个在 JavaScript 中,忽略不需要的参数的常见的方法。

// For example the array's forEach's callback has three params,
// value, index and the full array - if TypeScript didn't
// support discarding parameters, then you would have to
// include every option to make the functions match up:
// 例如,数组的 'forEach' 方法的回调有 3 个参数,值,索引,和整个数组。
// 如果 TypeScript 不支持丢弃参数,您必须包含所有的参数以使函数完备。

[createBall(1), createBall(2)].forEach((ball, _index, _balls) => {
console.log(ball);
});

// No one needs that.
// 没有人希望这样。

// Return types are treated like objects, and any differences
// are compared with the same object equality rules above.
// 返回值被视为对象,并且所有差异均按照上述对象相等性规则进行比较。

let createRedBall = (diameter: number) => ({ diameter, color: "red" });

createBall = createRedBall
createRedBall = createBall

// Where the first assignment works (they both have diameter)
// but the second doesn't (the ball doesn't have a color).
// 第一个赋值是有效的(他们都有 diameter),
// 第二个赋值不是有效的(ball 没有 color)。

0 comments on commit e5b0135

Please sign in to comment.