Skip to content
Home » [NEW] Conditional types in TypeScript | conditional type 0 – NATAVIGUIDES

[NEW] Conditional types in TypeScript | conditional type 0 – NATAVIGUIDES

conditional type 0: นี่คือโพสต์ที่เกี่ยวข้องกับหัวข้อนี้

This year TypeScript gained a new feature that punches far above its weight.

Working through our (enormous) backlog of unsorted TypeScript “Suggestions” and it’s remarkable how many of them
are solved by conditional types.

Ryan Cavanaugh, TypeScript maintainer

Conditional types probably aren’t something you’ll write every day, but you might end up using them indirectly all
the time. That’s because they’re great for ‘plumbing’ or ‘framework’ code, for dealing with API boundaries and
other behind-the-scenes kinda stuff. So, dear reader, read on! It’s always good to learn how the sausage is made.
Then you can make sausage of your own.

Typewurst! 🌭

Note: This is a straightforward adaptation of a 35-minute presentation given at
Futurice London’s TypeScript Night meetup,
and therefore provides more context than an ordinary blog post might. I hope a lot of that context is interesting
and useful even for seasoned TypeScript developers. If you’d prefer a no-frills experience, check out the
TypeScript 2.8 Release notes .

Your first conditional type

Here’s some plain JavaScript

1

2

3

4

5

function

process

(

text

)

{

return

text

&&

text

.

replace

(

/f/g

,

"p"

)

}

process

(

"foo"

).

toUpperCase

()

Reading the code, it’s clear to a human that the .toUpperCase() method call is safe. We can tell that whenever a
string is passed in to process, a string will be returned.

But notice that we could also pass something like null into the function, in which case null would be returned.
Then calling .toUpperCase() on the result would be an error.

Let’s add basic types to this function so we can let TypeScript worry about whether we are using it safely or not.

1

2

3

function

process

(

text

:

string

|

null

)

:

string

|

null

{

return

text

&&

text

.

replace

(

/f/g

,

"p"

)

}

Seems sensible. What happens if we try to use it like before?

1

2

// ⌄ Type Error! :(

process

(

"foo"

).

toUpperCase

()

TypeScript complains because it thinks that the result of process("foo") might be null, even though we clever
humans know that it won’t be. It can’t figure out the runtime semantics of the function on its own.

One way of helping TS understand the function better is to use ‘overloading’. Overloading involves providing
multiple type signatures for a single function, and letting TypeScript figure out which one to use in any given
context.

1

2

3

4

5

function

process

(

text

:

null

)

:

null

;

function

process

(

text

:

string

)

:

string

;

function

process

(

text

:

any

)

{

...

}

Here we’ve said that if we pass a string, it returns a string, and if we pass null, it returns null. (The
any type is ignored but still needs to be there for some reason 🤷‍️)

That works nicely:

1

2

3

4

// All clear!

process

(

"foo"

).

toUpperCase

()

// ⌄ Type Error! :)

process

(

null

).

toUpperCase

()

But there’s another use case that doesn’t work:

1

2

3

4

declare

const

maybeFoo

:

string

|

null

// ⌄ Type Error! :(

process

(

maybeFoo

)

TypeScript won’t let us pass something that is of type string | null because it’s not smart enough to collapse
the overloaded signatures when that’s possible. So we can either add yet another overload signature for the
string | null case, or we can be like (╯°□°)╯︵
┻━┻ and switch to using conditional types.

1

2

3

4

5

function

process

<

T

extends

string

|

null

>

(

text

:

T

)

:

T

extends

string

?

string

:

null

{

...

}

Here we’ve introduced a type variable T for the text parameter. We can then use T as part of a conditional
return type: T extends string ? string : null. You probably noticed that this looks just like a ternary
expression! Indeed, it’s doing the same kind of thing, but within the type system at compile time.

And that takes care of all our use cases:

1

2

3

typeof

process

(

"foo"

)

// => string

typeof

process

(

null

)

// => null

typeof

process

(

maybeFoo

)

// => string | null

So that’s what a conditional type is! A kind of ternary type expression. It always has this form:

1

A

extends

B

?

C

:

D

A, B, C, and D can be any old type expressions, but all the important stuff is happening on the left there.
In the A extends B condition.

Assignability

This extends keyword is the heart of a conditional type. A extends B means precisely that any value of type A
can safely be assigned to a variable of type B. In type system jargon we can say that “A is assignable to B”.

1

2

3

declare

const

a

:

A

const

b

:

B

=

a

// type check succeeds only if A is assignable to B

TypeScript decides which types are assignable to each other using an approach called ‘structural typing’. This kind
of type system started appearing in mainstream languages relatively recently (in the last 10 years or so), and
might be a little counterintuitive if you come from a Java or C# background.

You may have heard of ‘duck typing’ in relation to dynamically-typed languages. The phrase ‘duck typing’ comes from
the proverb

If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.

In duck typing, you judge a thing by how it behaves, rather than what it is called or who its parents are. It’s a
kind of meritocracy. Structural typing is a way of applying that same idea to a static compile-time type system.

So TypeScript only cares about what types can do, not what they are called or where they exist in a type hierarchy.

Take this simple example:

1

2

3

4

5

6

7

class

A

{}

class

B

{}

const

b

:

B

=

new

A

()

// ✔ all good

const

a

:

A

=

new

B

()

// ✔ all good

new

A

()

instanceof

B

// => false

TypeScript is happy treating two completely unrelated classes as equivalent because they have the same structure
and the same capabilities. Meanwhile, when checking the types at runtime, we discover that they are actually not
equivalent.

This is a notable example of where the semantics of TypeScript are at odds with JavaScript. It might seem like a
problem, but in practice structural typing is a lot more flexible than Java-esque ‘nominal’ typing, where names and
hierarchy matter. The two aren’t mutually exclusive, however. Some languages, like Scala and Flow, allow you to mix
and match to suit particular problems.

Aside from that, the way that assignability works with structural typing is very intuitive.

1

2

3

4

5

6

7

8

9

10

11

12

13

interface

Shape

{

color

:

string

}

class

Circle

{

color

:

string

radius

:

number

}

// ✔ All good! Circles have a color

const

shape

:

Shape

=

new

Circle

()

// ✘ Type error! Not all shapes have a radius!

const

circle

:

Circle

=

shape

Speaking structurally we can say that A extends B is a lot like ‘A is a superset of B‘, or, to be more
verbose, ‘A has all of B‘s properties, and maybe some more’.

There’s one minor caveat though, and that’s with ‘literal’ types. In TypeScript you can use literal values of
primitive types as types themselves.

1

2

3

4

let

fruit

:

"banana"

=

"banana"

// Type Error! "apple" is not assignable to "banana"

fruit

=

"apple"

The string "banana" doesn’t have more properties than any other string. But the type "banana" is still more
specific than the type string.

So another way to think of A extends B is like ‘A is a possibly-more-specific version of B‘.

Which brings us to ‘top’ and ‘bottom’ types: the least and most specific types, respectively.

In type theory a ‘top’ type is one which all other types are assignable to. It is the type you use to say “I have
absolutely no information about what this value is”. Think of it as the union of all possible types:

1

type

Top

=

string

|

number

|

{

foo

:

Bar

}

|

Baz

[]

|

...

|

TypeScript has two top types: any and unknown.

  • Using any is like saying “I have no idea what this value looks like. So, TypeScript, please assume I’m using it
    correctly, and don’t complain if anything I do seems dangerous”.
  • Using unknown is like saying “I have no idea what this value looks like. So, TypeScript, please make sure I
    check what it is capable of at run time.”

A ‘bottom’ type is one which no other types are assignable to, and that no values can be an instance of. Think of
it as the empty union type:

1

type

Bottom

=

TypeScript has one bottom type: never. That’s a nice descriptive name because it literally means this can never
happen.

Top and bottom types are useful to know about when working with conditional types. never is especially useful
when using conditional types to refine unions…

Refining unions with distributive conditional types

Conditional types let you filter out particular members of a union type. To illustrate, let’s say we have a union
type called Animal:

1

type

Animal

=

Lion

|

Zebra

|

Tiger

|

Shark

And imagine that we needed to write a function that used only those animals which are also cats. We might write
some helper type called ExtractCat to do that:

1

2

3

4

type

ExtractCat

<

A

>

=

A

extends

{

meow

()

:

void

}

?

A

:

never

type

Cat

=

ExtractCat

<

Animal

>

// => Lion | Tiger

I know lions and tigers don’t meow, but how cute would it be if they did ^_^

This seemed vague and magical to me at first. Let’s see what TypeScript is doing under the hood when it evaluates
ExtractCat<Animal>.

First, it applies ExtractCat recursively to all the members of Animal:

1

2

3

4

5

type

Cat

=

|

ExtractCat

<

Lion

>

|

ExtractCat

<

Zebra

>

|

ExtractCat

<

Tiger

>

|

ExtractCat

<

Shark

>

Then it evaluates the conditional types:

1

type

Cat

=

Lion

|

never

|

Tiger

|

never

And then something fun happens… Remember that no values can ever be of type never? That makes it totally
meaningless to include never in a union type, so TypeScript just gets rid of it.

1

type

Cat

=

Lion

|

Tiger

The TypeScript jargon for this kind of conditional type is distributive conditional type.

That ‘distribution’, where the union is unrolled recursively, only happens when the thing on the left of the
extends keyword is a plain type variable. We’ll see what that means and how to work around it in the next
section.

A real use-case for distributive conditional types.

A while ago I was building a Chrome extension. It had a ‘background’ script and a ‘view’ script that ran in
different execution contexts. They needed to communicate and share state, and the only way to do that is via
serializable message passing. I took inspiration from Redux and defined a global union of interfaces called
Action to model the messages that I wanted to be able to pass between the contexts.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

type

Action

=

|

{

type

:

"INIT"

}

|

{

type

:

"SYNC"

}

|

{

type

:

"LOG_IN"

emailAddress

:

string

}

|

{

type

:

"LOG_IN_SUCCESS"

accessToken

:

string

}

// ...

And then there was a global dispatch function that I could use directly to broadcast messages across contexts

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

declare

function

dispatch

(

action

:

Action

)

:

void

// ...

dispatch

({

type

:

"INIT"

})

// ...

dispatch

({

type

:

"LOG_IN"

,

emailAddress

:

"[email protected]"

})

// ...

dispatch

({

type

:

"LOG_IN_SUCCESS"

,

accessToken

:

"038fh239h923908h"

})


Try it in the TypeScript playground

This API is typesafe and it plays well with my IDE’s autocomplete and I could have left it there. I could have
moved on to other things.

But there’s this little voice inside my head. I think most developers have this voice.

INT. HIPSTER CO-WORKING SPACE - DAY

DAVID sits on an oddly-shaped orange chair.
His MacBook rests askew on a lumpy reclaimed
wood desk. He stares at colorful text on a
dark screen.

A tiny whisper.

              VOICE (V.O.)
    Psst!

David looks around for a moment and then
stares back at the laptop.

              VOICE (V.O.)
    Psst! Hey!

Startled this time, David looks around
again. He speaks to nobody in particular.

              DAVID
    Is someone there?

              VOICE (V.O.)
    It's me, the DRY devil.

David heaves a painful sigh of recognition.

              DAVID
    Not you again! Leave me alone!

              DRY DEVIL (V.O.)
    DRY stands for "Don't Repeat Yourself"

              DAVID
    I know, you say that every time! Now
    get lost!

              DRY DEVIL (V.O.)
    I've noticed an issue with your code.

              DAVID
    Seriously, go away! I'm busy solving
    user problems to create business value.

              DRY DEVIL (V.O.)
    Every time you call `dispatch` you
    are typing 6 redundant characters.

              DAVID
    Oh snap! You're right! I must fix this.

MONTAGE

David spends the next 2 hours wrestling
with TypeScript, accumulating a pile of
empty coffee cups and protein ball wrappers.

We’ve all been there.

I wanted the dispatch function to work like this:

1

2

3

4

5

// first argument is the 'type'

// second is any extra parameters

dispatch

(

"LOG_IN_SUCCESS"

,

{

accessToken

:

"038fh239h923908h"

})

Deriving the type for that first argument is easy enough.

1

2

type

ActionType

=

Action

[

"type"

]

// => "INIT" | "SYNC" | "LOG_IN" | "LOG_IN_SUCCESS"

But the type of the second argument depends on the first argument. We can use a type variable to model that
dependency.

1

2

3

4

declare

function

dispatch

<

T

extends

ActionType

>

(

type

:

T

,

args

:

ExtractActionParameters

<

Action

,

T

>

)

:

void

Woah woah woah, what’s this ExtractActionParameters voodoo?

It’s a conditional type of course! Here’s a first attempt at implementing it:

1

type

ExtractActionParameters

<

A

,

T

>

=

A

extends

{

type

:

T

}

?

A

:

never

This is a lot like the ExtractCat example from before, where we were were refining the Animals union by
searching for something that can meow(). Here, we’re refining the Action union type by searching for an
interface with a particular type property. Let’s see if it works:

1

2

type

Test

=

ExtractActionParameters

<

Action

,

"LOG_IN"

>

// => { type: "LOG_IN", emailAddress: string }

Almost there! We don’t want to keep the type field after extraction because then we would still have to specify
it when calling dispatch. And that would somewhat defeat the purpose of this entire exercise.

We can omit the type field by combining a mapped type with a conditional type and the keyof operator.

A mapped type lets you create a new interface by ‘mapping’ over a union of keys. You can get a union of keys
from an existing interface by using the keyof operator. And finally, you can remove things from a union using a
conditional type. Here’s how they play together (with some inline test cases for illustration):

1

2

3

4

5

6

7

8

9

10

type

ExcludeTypeKey

<

K

>

=

K

extends

"type"

?

never

:

K

type

Test

=

ExcludeTypeKey

<

"emailAddress"

|

"type"

|

"foo"

>

// => "emailAddress" | "foo"

// here's the mapped type

type

ExcludeTypeField

<

A

>

=

{

[

K

in

ExcludeTypeKey

<

keyof

A

>

]

:

A

[

K

]

}

type

Test

=

ExcludeTypeField

<

{

type

:

"LOG_IN"

;

emailAddress

:

string

}

>

// => { emailAddress: string }

Then we can use ExcludeTypeField to redefine ExtractActionParameters.

1

2

3

type

ExtractActionParameters

<

A

,

T

>

=

A

extends

{

type

:

T

}

?

ExcludeTypeField

<

A

>

:

never

And now the new version of dipsatch is typesafe!

1

2

3

4

5

6

7

8

9

10

11

12

13

14

// All clear! :)

dispatch

(

"LOG_IN_SUCCESS"

,

{

accessToken

:

"038fh239h923908h"

})

dispatch

(

"LOG_IN_SUCCESS"

,

{

// Type Error! :)

badKey

:

"038fh239h923908h"

})

// Type Error! :)

dispatch

(

"BAD_TYPE"

,

{

accessToken

:

"038fh239h923908h"

})


Try it in the TypeScript playground

But there’s one more very serious problem to address: If the action has no extra parameters, I still have to pass a
second empty argument.

1

dispatch

(

"INIT"

,

{})

That’s four whole wasted characters! Cancel my meetings and tell my partner not to wait up tonight! We need to
fix. this.

The naïve thing to do would be to make the second argument optional. That would be unsafe because, e.g. it would
allow us to dispatch a "LOG_IN" action without specifying an emailAddress.

Instead, let’s overload the dispatch function.

1

2

3

4

5

6

7

8

9

10

// And let's say that any actions that don't require

// extra parameters are 'simple' actions.

declare

function

dispatch

(

type

:

SimpleActionType

)

:

void

// this signature is just like before

declare

function

dispatch

<

T

extends

ActionType

>

(

type

:

T

,

args

:

ExtractActionParameters

<

Action

,

T

>

)

:

void

type

SimpleActionType

=

ExtractSimpleAction

<

Action

>

[

'type'

]

How can we define this ExtractSimpleAction conditional type? We know that if we remove the type field from an
action and the result is an empty interface, then that is a simple action. So something like this might work

1

type

ExtractSimpleAction

<

A

>

=

ExcludeTypeField

<

A

>

extends

{}

?

A

:

never

Except that doesn’t work. ExcludeTypeField<A> extends {} is always going to be true, because {} is like a top
type for interfaces. Pretty much everything is more specific than {}.

We need to swap the arguments around:

1

type

ExtractSimpleAction

<

A

>

=

{}

extends

ExcludeTypeField

<

A

>

?

A

:

never

Now if ExcludeTypeField<A> is empty, the condition will be true, otherwise it will be false.

But this still doesn’t work! On-the-ball readers might remember this:

That ‘distribution’, where the union is unrolled recursively, only happens when the thing on the left of the
extends keyword is a plain type variable. We’ll see what that means and how to work around it in the next
section.

— Me, in the previous section

Type variables are always defined in a generic parameter list, delimited by < and >. e.g.

1

2

3

4

5

type

Blah

<

These

,

Are

,

Type

,

Variables

>

=

...

function

blah

<

And

,

So

,

Are

,

These

>

()

{

...

}

And if you want a conditional type to distribute over a union, the union a) needs to have been bound to a type
variable, and b) that variable needs to appear alone to the left of the extends keyword.

e.g. this is a distributive conditional type:

1

type

Blah

<

Var

>

=

Var

extends

Whatever

?

A

:

B

and these are not:

1

2

type

Blah

<

Var

>

=

Foo

<

Var

>

extends

Whatever

?

A

:

B

type

Blah

<

Var

>

=

Whatever

extends

Var

?

A

:

B

When I discovered this limitation I thought that it exposed a fundamental shortcoming in the way distributive
conditional types work under the hood. I thought it might be some kind of concession to algorithmic complexity. I
thought that my use case was too advanced, and that TypeScript had just thrown its hands up in the air and said,
“Sorry mate, you’re on your own”.

But it turns out I was wrong. It is just a pragmatic language design decision to avoid extra syntax, and you can
work around it easily:

1

2

3

4

5

type

ExtractSimpleAction

<

A

>

=

A

extends

any

?

{}

extends

ExcludeTypeField

<

A

>

?

A

:

never

:

never

All we did is wrap the meat of our logic in a flimsy tortilla of inevitability, since the outer condition
A extends any will, of course, always be true.

And finally we can delete those four characters 🎉🕺🏼💃🏽🎈

1

dispatch

(

"INIT"

)

That’s one yak successfully shaved ✔

TypeScript provides a couple of built-in types that we could have used in this section:

1

2

3

4

5

// Exclude from U those types that are assignable to T

type

Exclude

<

U

,

T

>

=

U

extends

T

?

never

:

U

// Extract from U those types that are assignable to T

type

Extract

<

U

,

T

>

=

U

extends

T

?

U

:

never

e.g. instead of defining ExcludeTypeField like this:

1

type

ExcludeTypeField

<

A

>

=

{

[

K

in

ExcludeTypeKey

<

keyof

A

>

]

:

A

[

K

]

}

we could have done this:

1

type

ExcludeTypeField

<

A

>

=

{

[

K

in

Exclude

<

keyof

A

,

"type"

>

]

:

A

[

K

]

}

And instead of defining ExtractActionParameters like this:

1

2

3

type

ExtractActionParameters

<

A

,

T

>

=

A

extends

{

type

:

T

}

?

ExcludeTypeField

<

A

>

:

never

we could have done this:

1

type

ExtractActionParameters

<

A

,

T

>

=

ExcludeTypeField

<

Extract

<

A

,

{

type

:

T

}

>>

💡 Exercise for the intrepid reader

Notice that this still works.

1

dispatch

(

"INIT"

,

{})

Use what you’ve learned so far to make it an error to supply a second argument for ‘simple’ actions.

Destructuring types with infer

Conditional types have another trick up their sleeve: the infer keyword. It can be used anywhere in the type
expression to the right of the extends keyword. It gives a name to whichever type would appear in that place.
e.g.

1

2

3

4

5

6

type

Unpack

<

A

>

=

A

extends

Array

<

infer

E

>

?

E

:

A

type

Test

=

Unpack

<

Apple

[]

>

// => Apple

type

Test

=

Unpack

<

Apple

>

// => Apple

It handles ambiguity gracefully:

1

2

type

Stairs

=

Unpack

<

Apple

[]

|

Pear

[]

>

// => Apple | Pear

You can even use infer multiple times.

1

2

3

4

5

6

7

type

Flip

<

T

>

=

T

extends

[

infer

A

,

infer

B

]

?

[

B

,

A

]

:

never

type

Stairs

=

Flip

<

[

Pear

,

Apple

]

>

// => [Apple, Pear]

type

Union

<

T

>

=

T

extends

[

infer

A

,

infer

A

]

?

A

:

never

type

Stairs

=

Union

<

[

Apple

,

Pear

]

>

// => Apple | Pear

Other built-in conditional types

We’ve already seen Exclude and Extract, and TypeScript provides a few other conditional types out of the box.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

// Exclude null and undefined from T

type

NonNullable

<

T

>

=

T

extends

null

|

undefined

?

never

:

T

// Obtain the parameters of a function type in a tuple

type

Parameters

<

T

>

=

T

extends

(...

args

:

infer

P

)

=>

any

?

P

:

never

// Obtain the parameters of a constructor function type in a tuple

type

ConstructorParameters

<

T

>

=

T

extends

new

(...

args

:

infer

P

)

=>

any

?

P

:

never

// Obtain the return type of a function type

type

ReturnType

<

T

>

=

T

extends

(...

args

:

any

[])

=>

infer

R

?

R

:

any

// Obtain the return type of a constructor function type

type

InstanceType

<

T

>

=

T

extends

new

(...

args

:

any

[])

=>

infer

R

?

R

:

any

Further reading

[NEW] Conditional Sentence Câu If | conditional type 0 – NATAVIGUIDES

Conditional Sentence (câu điều kiên if) cũng được tính là một câu phức với independent clause và dependent clause. Điểm đặc biệt của câu điều kiện này là chúng dành để đưa ra giả định. Giả định thì có thể đúng, có thể sai. Có thể là hoàn toàn không có thật, có thể là có thể xảy ra. Trong bài này, chúng ta sẽ tập trung xem qua tất cả những điểm ngữ pháp liên quan đến việc đưa ra câu giả định (hypothesis).

Cần lưu ý là Conditional Sentence If – Câu If chỉ là một trong nhiều cách để đưa GIả Định mà thôi. Có thể các bạn sẽ muốn khám phá toàn bộ chuyên đề Conditional Sentence – Câu Điều Kiện đấy.

Conditional Sentence Câu If

Modal Verb – Trợ Động Từ – có khá nhiều loại, và chúng thêm một hàm ý nhất định vào trong động từ. Tuy nhiên, khi chúng ta dùng chúng trong câu điều kiện, chúng lại được phân loại và biến đổi một chút nữa. Đó là lý do chúng ta nên tìm hiểu về chúng trước khi xem qua bài Conditional Sentence Câu IF.

Các bạn có thể tìm hiểu về trợ động từ trong câu điều kiện tại bài Modal Verb in Conditional Sentence.

Loại câu điều kiện đầu tiên phải kể đến là Zero Conditional Sentence. Chúng dành cho những câu luôn luôn đúng(?). Và cách sử dụng của chúng cũng khá đặc biệt. Zero Conditional Sentence là loại câu điều kiện duy nhất (trong câu IF) không cần dùng Modal Verb ở mệnh đề chính.

Các bạn có thể tìm hiểu trọn vẹn về loại câu IF này tại bài Zero Conditional Sentence – Câu Điều Kiện 0.

Câu điều kiện loại 1, hay còn gọi là có thật ở hiện tại. Tuy nhiên, người ta còn dùng khái niệm này để chỉ câu điều kiện có thể xảy ra ở quá khứ.

Ở hiện tại thì đơn giản rồi nhưng khi nói ở quá khứ mọi việc lại trở nên phức tạp hơn. Vì vậy, thầy đã có một bài riêng cho nó. Các bạn xem qua bài Conditional Type 1 – Câu điều kiện loại một để tìm hiểu thêm nhé.

Đây là câu điều kiện loại 2, dành riêng cho những sự vật sự việc không thể diễn ra ở hiện tại. Khi chúng ta muốn đề cập đến sự bất khả thi (về khả năng diễn ra) của một hành động ở hiện tại, chúng ta sẽ dùng loại câu này.

Dùng câu điều kiện loại 2 như thế nào? Cần chú ý điều gì? Mời các bạn xem bài Conditional Sentence Type 2 – Câu Điều Kiện Loại 2 nhé.

Đây là nhóm “đô con” nhất trong mớ câu IF. Câu điều kiện loại 3 cho phép bạn diễn đạt những hành động không thể xảy ra trong quá khứ. Cấu trúc này được dùng để giả định những sự việc đã xảy ra và không thể thay đổi được.

Các bạn có thể tham khảo toàn bộ bài viết về câu IF này tại Conditional Type 3 – Câu Điều Kiện Loại 3.

Và cuối cùng là các trường hợp kết hợp câu điều kiện ở những mốc thời gian khác nhau. Có thể là ở quá khứ với hiện tại hoặc hiện tại với quá khứ. Nhưng dù như thế nào thì chỉ có mệnh đề không thật chơi với mệnh đề không thật. Và giả định có thật đi với giả định có thật.

Trong bài này, chúng ta sẽ cùng tìm hiểu về các cách kết hợp những mệnh đều câu điều kiện lại. Các bạn hãy đọc bài Mixed Conditional Sentences nhé.

 

Một Số Lưu Ý

Ngoài ra có một số lưu ý sau khi chúng ta sử dụng câu IF

What If + Clause?

Khi chúng ta dùng What if + mọt mệnh đề, người nghe sẽ hiểu ngầm một trong hai trường hợp:

  • What if + Clause? =

    What would happen if + Clause:

    không thật ở

    hiện tại

    • Hey, what if the sun rose in the West?
    • I have too much work to do. What if there were 48 hours in a day?
  • What if + Clause? =

    What would have happened + if + Clause

    : không thật ở

    quá khứ.

    • Well, what if Steve hadn’t been Captain America?
    • I didn’t see him yesterday, so he broke up with me. What if I had seen him yesterday?

Các bạn chú ý là cả hai phần trên đều dùng cho KHÔNG THẬT (Unreal) nhé. Một cái không thật ở hiện tại (dùng Past Subjunctive, nghĩa là Simple Past, nhưng WERE cho tất cả các ngôi), một cái ở quá khứ (dùng Past Perfect).

If + it is + adjective = If + ADJECTIVE

Chúng ta có thể rút gọn “if it is adjective” thành “if adjective.” Rất đơn giản, chỉ việc bỏ it is đi và không thay đổi gì thêm:

  • If it is possible, please call me.
    =

    If possible

    , please call me.

  • I think you should kiss her if it is necessary.
    =I think you should kiss her

    if necessary

    .

  • If it is important to you, I will do it.
    =

    If important

    , I will do it.

If so/ If not

Chúng ta có thể dùng IF kết hợp với SO (khẳng định) hoặc NOT (phủ định) để thay thế cho một câu phía trước đó. Ví dụ:

  • There is a possibility that Jane refuses our offer.

    If so

    , we’ll have to find another person.
    (=If Jane refuses our offer, we’ll have to find another person.)

  • Perhaps Tom will come.

    If not,

    I’ll take his place.
    (=If Tom doesn’t come, I’ll take his place.)

  • Perhaps Tom won’t come.

    If not

    , I’ll take his place.
    (=If Tom doesn’t come, I’ll take his place.)

Ồh, hai ví dụ cuối kỳ lạ đúng không? Tại tiếng Anh nó quy định thế các bạn ạ. Khi vế trước phủ định thì chúng ta dùng IF NOT sẽ hiểu là “nếu như vậy.” Trong trường hợp khẳng định thì chúng ta dùng IF NOT lại hiểu là “nếu không như vậy.”

Modal Verb in Conditional Clauses

Phần lớn trường hợp, trong mệnh đề chứ IF sẽ không được sử dụng Modal Verbs. Tuy nhiên, ở một số trường hợp nhất định, chúng ta có thể sử dụng Modal verb trong mệnh đề chứa IF để đưa thêm một nét nghĩa nhất định vào động từ.

 + 

Khi ta dùng Should trong vế câu điều kiện, người nghe sẽ hiểu là hành động / sự kiện đó được diễn ra một cách bất ngờ, vô tình, không có tính toán.

(nếu vô tình gặp được Carol)

Ngoài ra còn một trường hợp kết hợp với modal verb là:

If + will/would

Chúng ta còn có thể sử dụng will và would trong mệnh đề IF để:

  1. Diễn tả ý “tự nguyện / tự giác / đồng ý” làm điều gì:
    • (nếu Clare đồng ý gặp chúng ta ở sân bay).
    • (nếu mày chịu dừng la một chút thì tao sẽ giải thích cho).

  2. Nhấn mạnh sự nghi ngờ của chúng ta tới kết quả ở mệnh đề chính:
    • (nếu mà chạy cứu được trái đất thì ok, tao ngừng chạy).
    • If it really would be anything that makes her love me, I’d do right now.

Chúng ta có thể đảo ngữ câu điều kiện để nhấn mạnh sự giả định đấy. Các bạn theo dõi bài viết Inversion of Conditional Sentences nhé.

Và đó là tất cả những điểm ngữ pháp có thể đưa ra giả định và câu điều kiện If. Thầy nghĩ các bạn sẽ muốn xem thêm toàn bộ thông tin về Conditional Sentence – Câu Điều Kiện đấy. Vì câu If chỉ là một phần nhỏ trong đó mà thôi.

Nếu bạn thấy bài viết này hữu ích, hãy kết nối với LearningEnglishM qua kênh Youtube nhé! Thank you!


Conditionals – Type 0 / Zero conditional sentences / If Clause 0 – English Grammar Lesson


An English grammar lesson about conditional sentences type zero ( Zero conditionals).
This type expresses something that is always true facts / general truth.

นอกจากการดูบทความนี้แล้ว คุณยังสามารถดูข้อมูลที่เป็นประโยชน์อื่นๆ อีกมากมายที่เราให้ไว้ที่นี่: ดูเพิ่มเติม

Conditionals - Type 0 / Zero conditional sentences / If Clause 0 - English Grammar Lesson

50+ Advanced Phrases For English Conversations


Learn 50+ Common English phrases used in advanced conversations! Improve your speaking skills and learn advanced techniques to speak confidently!
Check out 👉https://heylady.io/mmmenglish where women meet to practice speaking English together!
This is the best video to help intermediate language students speak in advanced English conversations! All the phrases you need to have successful English conversations!
Read the full transcript of this lesson on my blog here:\r
https://www.mmmenglish.com/2020/03/06/50advancedphrasesforenglishconversations/
\r
StayHomeWithMe StayHome WithMe Learn mmmEnglish EnglishConversation SpeakEnglish AdvancedEnglish ConfidentEnglish YouTubeTeacher TheLadiesProject EnglishWithEmma \r
\r

\r
Hey Lady! 💃 is an online community for women learning English. Meet women around the world, find speaking partners, study English and learn about different cultures! Hey Lady! is a place for international women to build confidence and fluency in English conversations, in a safe, supportive online environment. 🌈 🤸🏻‍♀️ 💫
⭐️ Learn More: https://heylady.io/mmmenglish
⭐️ Don’t miss our special prelaunch offer, get 1 month free if you sign up by 31st August.
\r

🤸🏻‍♀️ Have you seen my brand 🌟NEW Prepositions 8×8 Course?
16+ videos to help you master prepositions
👉🏻Try it FREE!👈🏻 https://bit.ly/prepositions8x8
8 x prepositions
8 x ways to use them
8 x imitation lessons (practise speaking AND pronunciation)

More English Language Tools I recommend!\r
⭐️Improve your English pronunciation and expression by imitating a native English speaker: https://www.mmmenglish.com/imitation\r
⭐️Try Grammarly Grammar Checker it’s FREE! https://www.grammarly.com/mmmenglish\r
⭐️English Listening practice Try Audible for FREE! http://www.audibletrial.com/mmmEnglish \r
\r
\r
\r
Find mmmEnglish here! \r
mmmEnglish Website: http://bit.ly/mmmEnglish \r
On Facebook: http://bit.ly/mmmEnglishFB\r
On Instagram: http://bit.ly/mmmEnglishInsta \r
SUBSCRIBE ➡️ http://bit.ly/Subscribe2mmmEnglish (New lessons every Friday!)\r
\r
\r
\r
TRANSLATE THIS VIDEO!\r
Do your friends a favour and help to translate this lesson into your native language! Contribute subtitles translations here: \r
http://www.youtube.com/timedtext_video?ref=share\u0026v=TR0JZiapxXM
Your name will be featured underneath the video 😝

50+ Advanced Phrases For English Conversations

Zero Conditional – English Grammar Lesson


In this English grammar lesson we look at Zero Conditional sentences, when to use them and how to make them.
Zero conditionals are used for facts that are generally true and do not change. It refers to a general situation that always happen (for example in the rules of a game) if a condition is met. The condition always has the same result.
The zero conditional uses the present simple in the ifclause and in the main clause.
We also look at the word order of zero conditionals and how there are two ways of writing them.
Of course we have included many examples sentences of zero conditionals.
Zero Conditionals are also known as Type 0 conditionals
See our complete English lesson here:
https://www.woodwardenglish.com/lesson/zeroconditional/
ZeroConditional Conditionals EnglishGrammar
💚💚💚 How to support WOODWARD ENGLISH 💚💚💚
📗 ENGLISH LANGUAGE RESOURCES 📗
🌿 https://www.woodwardenglish.com/shop/
English Resources for Teachers and Parents. (PDF and PPT Ideal for ESOL students or homeschool). These PDFs are also great for those studying English alone.
⭐ LIVE 1ON1 ENGLISH LESSONS ⭐
🌿 https://go.italki.com/woodward (affiliate)
Get $10 USD in italki credits after booking your first language lesson.
The most EFFICIENT way to reach English fluency!
Customized 1on1 lessons with professionally qualified teachers that cater to students’ learning needs and interests.
Speaking with humans is the best way to learn English.
🎥 JOIN Woodward English on YouTube 🎥
🌿 https://www.youtube.com/user/WoodwardEnglish/join
Exclusive videos only for members.
Exclusive members only posts in our YT community tab
Exclusive Discord channel.
Loyalty badges next to your name in comments and live chat
Custom emoji to use in live chat
📗 BOOKS I RECOMMEND 📗
🌿 Practical English Usage – Michael Swan https://amzn.to/3lG2AMU
🌿 English Grammar in Use – Raymond Murphy https://amzn.to/2YOrjoX
🌿 Official Cambridge Guide to IELTS https://amzn.to/3lG489i
🌿 The Practice of English Language Teaching – Jeremy Harmer https://amzn.to/2YSsYub
🌿 Oxford Advanced Learner’s Dictionary https://amzn.to/3mOKN5f
As an Amazon Associate I earn from qualifying purchases at no extra cost to you.
Each purchase of the above helps me to continue creating more free English language resources on YouTube and the Woodward English websites.

💚💚💚 Do you like WOODWARD ENGLISH and want to learn more? 💚💚💚
Here are the next steps to improving your English:
1) SUBSCRIBE to the WOODWARD ENGLISH channel so you know when I create new videos to help you improve your English.
🌿 https://www.youtube.com/subscription_center?add_user=WoodwardEnglish
Make sure you click the notification bell so you know immediately when I upload a new English lesson.
2) See our FREE ENGLISH LESSONS and language learning articles:
🌿 https://www.grammar.cl (Grammar lessons)
🌿 https://www.vocabulary.cl (Vocabulary lessons)
🌿 https://www.woodwardenglish.com (Free English courses)
3) LET’S CONNECT!
🌿 https://twitter.com/WoodwardEnglish
🌿 https://www.facebook.com/WoodwardEnglish/
🌿 https://www.instagram.com/woodwardenglish/
🌿 https://www.pinterest.com/woodwardenglish/
✉️ Send us a postcard from your country ✉️
Rob Woodward
P.O. Box 38438
Howick
Auckland 2145
New Zealand
NOTE: Our English lessons and English language resources are for people over the age of 13.
Have an awesome day!
Rob Woodward

Zero Conditional - English Grammar Lesson

Learn English Grammar: The 4 Conditionals


Do conditionals in English drive you crazy? They’re so easy to get mixed up! There are four conditionals in English grammar, numbered zero through three. So in this lesson I’ll give you an overview of all four, with examples of each. If you watch this video and do the quiz at https://www.engvid.com/learnenglishgrammarthe4conditionals/ you will have a better understanding of conditionals in English. (That last sentence is an example of the first conditional!)

Learn English Grammar: The 4 Conditionals

Câu điều kiện loại 0 (Conditional Sentences type 0)


Câu điều kiện loại 0 (Conditional Sentences type 0)

Câu điều kiện loại 0 (Conditional Sentences type 0)

นอกจากการดูบทความนี้แล้ว คุณยังสามารถดูข้อมูลที่เป็นประโยชน์อื่นๆ อีกมากมายที่เราให้ไว้ที่นี่: ดูบทความเพิ่มเติมในหมวดหมู่LEARN FOREIGN LANGUAGE

ขอบคุณที่รับชมกระทู้ครับ conditional type 0

Leave a Reply

Your email address will not be published. Required fields are marked *