<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lucas jin</title>
    <description>The latest articles on DEV Community by Lucas jin (@lucas1004jx).</description>
    <link>https://dev.to/lucas1004jx</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F734333%2F24bd88dc-e6c8-42c3-ae9a-82ff5fd33f6f.JPG</url>
      <title>DEV Community: Lucas jin</title>
      <link>https://dev.to/lucas1004jx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lucas1004jx"/>
    <language>en</language>
    <item>
      <title>Mocking Modules in Jest: Three Powerful Techniques</title>
      <dc:creator>Lucas jin</dc:creator>
      <pubDate>Tue, 02 Apr 2024 10:58:13 +0000</pubDate>
      <link>https://dev.to/lucas1004jx/mocking-modules-in-jest-three-powerful-techniques-4ol6</link>
      <guid>https://dev.to/lucas1004jx/mocking-modules-in-jest-three-powerful-techniques-4ol6</guid>
      <description>&lt;p&gt;Jest offers three effective methods to mock modules in your tests, enabling you to isolate and control external dependencies for focused testing. Here's a detailed breakdown of each approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Direct Mocking in the Test File (Using &lt;code&gt;jest.mock&lt;/code&gt;):&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Ideal for mocking specific modules within the context of a single test file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Syntax:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jest.mock('module-to-mock', () =&amp;gt; ({
  // Mock implementation for the module
}));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useSite } from 'src/context/SiteContext'; // Import the mocked module
jest.mock('src/context/SiteContext', () =&amp;gt; ({
  useSite: jest.fn(),
}));
const useSiteMockImpelmetation = (market: string) =&amp;gt; {
  (useSite as any).mockImplementation(() =&amp;gt; {
    return {
      config: {
        market,
      },
    };
  });
};
 it('should show 4 list item if is spanish market', () =&amp;gt; {
    mockMarket('es');
    renderComponent();
    const items = screen.getAllByRole('listitem');
    expect(items).toHaveLength(4);
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Global Mocking in jest.setup.ts:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Suitable for globally mocking modules across all test files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Location: Create a file named jest.setup.ts (or .js) in your project's root directory.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jest.mock('module-to-mock', () =&amp;gt; ({
  // Mock implementation for the module
}));
Example (in jest.setup.ts):



jest.mock('next-i18next', () =&amp;gt; ({
  useTranslation: () =&amp;gt; ({
    t: (key: string) =&amp;gt; key,
  }),
}));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Manual Mocking in the &lt;code&gt;__mocks__&lt;/code&gt; Folder: (Manual Mocks · Jest )&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Useful when the mocked module has complex logic or requires custom configuration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a directory named &lt;strong&gt;mocks&lt;/strong&gt; within the same directory as the module you want to mock.&lt;/li&gt;
&lt;li&gt;Inside &lt;code&gt;__mocks__&lt;/code&gt;, create a file with the same name as the module (including extension). This file will contain your mock implementation.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Example (assuming &lt;code&gt;src/context/SiteContext.tsx&lt;/code&gt; is the module to mock):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create &lt;strong&gt;mocks&lt;/strong&gt;/src/context/SiteContext.tsx.&lt;/li&gt;
&lt;li&gt;Implement your mock logic in this file.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jest.mock('src/context/SiteContext', () =&amp;gt; ({
  useSite: jest.fn(() =&amp;gt; ({ 
    config: {
      market:'us'
      }
  })),
}));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in the test file, we can use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jest.mock('src/context/SiteConfigContext');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The useSite mock will automatically have the mock value that defined in the &lt;code&gt;__mocks__/src/context/SiteContext.tsx&lt;/code&gt; file&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Props and cons:
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Direct Mocking (&lt;code&gt;jest.mock&lt;/code&gt; in Test File)&lt;/td&gt;
&lt;td&gt;Targeted: Mocks apply only to a specific test file. - Simple: Easy to set up for basic mocking needs. - Clear: Mock behavior stays within the test case.&lt;/td&gt;
&lt;td&gt;Limited Scope: Mocks are not shared across other tests. - Repetition: May lead to code duplication if mocking the same module in multiple tests.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Global Mocking (jest.setup.ts)&lt;/td&gt;
&lt;td&gt;Consistency: Mocks are applied consistently across all tests. - Convenience: No need to repeat mock definitions for each test.&lt;/td&gt;
&lt;td&gt;Global Impact: Accidental side effects in mocks can affect all tests. - Less Control: Less granular control over mock behavior compared to direct mocking.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manual Mocking (&lt;strong&gt;mocks&lt;/strong&gt; Folder)&lt;/td&gt;
&lt;td&gt;Flexibility: Suitable for complex mocking logic or custom configurations. - Organization: Keeps mock code separate for better maintainability.&lt;/td&gt;
&lt;td&gt;Setup: Requires creating a dedicated folder structure. - Potential Issues: May be harder to debug if mock logic becomes intricate.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  Choosing the Right Method:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For basic mocks within a single test: Direct mocking with jest.mock is straightforward and keeps code focused.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For consistent global mocking: Use jest.setup.ts when you need the same mock behavior across all tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For complex or reusable mock logic: Manual mocking with the &lt;strong&gt;mocks&lt;/strong&gt; folder offers flexibility and organization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We always can use jest.mock('path') to unmock the mock file &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>jest</category>
      <category>testing</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Typescript generic type - basic concept</title>
      <dc:creator>Lucas jin</dc:creator>
      <pubDate>Mon, 25 Apr 2022 09:38:50 +0000</pubDate>
      <link>https://dev.to/one-beyond/typescript-generic-type-basic-concept-2ebc</link>
      <guid>https://dev.to/one-beyond/typescript-generic-type-basic-concept-2ebc</guid>
      <description>&lt;p&gt;If it's your first time working with a Typescript project, the generic type can be intimidating. It's already complicated dealing with all other normal types, the generic type makes it look like we are working with another different language rather than Javascript.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to declare a type with a defined type value
&lt;/h2&gt;

&lt;p&gt;To talk about the generic type, let's see an example of how to declare a type with a defined type value in Typescript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type A = number[]

interface AB {
  a: A
  b: string
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have declared a type A, which is an array of numbers, and an interface B, which has properties a and b. It's quite simple and clear, right? &lt;/p&gt;

&lt;p&gt;But now if we want another type, which will be an array of strings and another interface that will contain this type, what should we do? Of course, we can simply create another type&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type C = string[]

interface CD {
  c: C 
  d: string
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to declare a generic type
&lt;/h2&gt;

&lt;p&gt;But don't you remember one of the principles of software development is &lt;strong&gt;"Don't repeat yourself"&lt;/strong&gt;? In this case Typescript generic type comes to the rescue. &lt;strong&gt;The purpose of the generic type is to create reusable types&lt;/strong&gt;, does it sound familiar, you may have heard that the functions are used to create reusable code as well. It turns out they are quite similar. Let's see how to create a generic type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type A&amp;lt;T&amp;gt; = T[]

interface AB&amp;lt;T&amp;gt; {
  a: A&amp;lt;T&amp;gt;
  b: string
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You see, the difference between the normal type and the generic type is that the generic type has an angle bracket. And also when we declare a type like this &lt;code&gt;type A = number[]&lt;/code&gt; we know the type is an array of numbers, but we don't know what type is yet when we declare the generic type. That's why it's called generic type, because it can be any type. &lt;/p&gt;

&lt;p&gt;As I said before, the generic type and the function are very similar. You can think this way: here we declared a type A, and we pass a parameter T to it, then we return a type of array of T. So when we use the generic type, we have to pass an argument to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type A&amp;lt;T&amp;gt; = T[]

const a:A&amp;lt;number&amp;gt; = [1, 2, 3] // Correct.

const a:A&amp;lt;string&amp;gt; = ['1', '2', '3'] // Correct.

const a:A&amp;lt;number | string&amp;gt; = ['1','2', 3] //Correct

const a:A&amp;lt;number&amp;gt; = ['1','2','3'] //Error. Type 'string' is not assignable to type 'number'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ab:AB&amp;lt;number&amp;gt; = {
  a:[1, 2, 3], // Correct
  b:'b'
}

const ab:AB&amp;lt;string&amp;gt; = {
  a:['1', '2', '3'], // Correct
  b:'b'
}

const ab:AB&amp;lt;number&amp;gt; = {
  a:['1','2','3'], // Error. Type 'string' is not assignable to type 'number'.
  b:'b'
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this way, we can create any type we want, as long as they share the same structure. You can often see that people use &lt;strong&gt;&lt;em&gt;T&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;U&lt;/em&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;em&gt;K&lt;/em&gt;&lt;/strong&gt; as the generic type parameter, but you really can name it whatever you want, maybe a semantic word is a good idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  Declare generic type with default type
&lt;/h2&gt;

&lt;p&gt;Like functions, we also can pass a default type to the generic type, in case we don't pass any type to it, it will be set to the default type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type A&amp;lt;T = string&amp;gt; = T[]

interface AB&amp;lt;T = number&amp;gt; {
  a: A&amp;lt;T&amp;gt;
  b: string
}


const a: A = ['1','2','3'] // Correct

const a: A = [ 1, 2, 3] // Error. Type 'number' is not assignable to type 'string'.

const ab: AB = {
  a:[ 1, 2, 3], // Correct
  b:'b'
}

const ab: AB = {
  a:[ '1', '2', '3'], // Error. Type 'string' is not assignable to type 'number'.
  b:'b'
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Use more than one parameter
&lt;/h2&gt;

&lt;p&gt;In the above examples, we see how to create a generic type with a single parameter, but the truth is you can use as many parameters as you want, just like functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface AB&amp;lt;T,U&amp;gt; {
  a: T[]
  b: U
}

const ab:AB&amp;lt;number, string&amp;gt; = {
  a: [1,2,3],
  b: '123'
} // Correct

const ab:AB&amp;lt;number, string&amp;gt; = {
  a: ['1','2','3'], // Error. Type 'string' is not assignable to type 'number'.
  b: 123 // Error. Type 'number' is not assignable to type 'string'.
} 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, you can combine the default type with several parameters, but there is one condition that the optional type parameters can't be added before the required parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface AB&amp;lt;T = number, U = string&amp;gt; { // Correct.
  a: T[]
  b: U
}

interface AB&amp;lt;T, U = string&amp;gt; { // Correct.
  a: T[]
  b: U
}

interface AB&amp;lt;T = number ,U&amp;gt; { // Error. Required type parameters may not follow optional type parameters.
  a: T[]
  b: U
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>typescript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>What you need to know about Typescript types</title>
      <dc:creator>Lucas jin</dc:creator>
      <pubDate>Mon, 11 Apr 2022 10:11:44 +0000</pubDate>
      <link>https://dev.to/one-beyond/what-you-need-to-know-about-typescript-types-2bd2</link>
      <guid>https://dev.to/one-beyond/what-you-need-to-know-about-typescript-types-2bd2</guid>
      <description>&lt;p&gt;When we are talking about types in typescript, what is the first thing that comes to your  mind? You may think:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;number (1,2,3)&lt;/li&gt;
&lt;li&gt;string ('hello',''world')&lt;/li&gt;
&lt;li&gt;boolean (true, false)&lt;/li&gt;
&lt;li&gt;object ({name:'Jon',age:'30'})&lt;/li&gt;
&lt;li&gt;function ((x,y)=&amp;gt; x + y) &lt;/li&gt;
&lt;li&gt;undefined &lt;/li&gt;
&lt;li&gt;null &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes, these are some possible types in Typescript system. Before you run the code, typescript uses them to check for errors.&lt;/p&gt;

&lt;p&gt;A variable can just have one type... &lt;strong&gt;&lt;em&gt;wow! stop there!&lt;/em&gt;&lt;/strong&gt; you may start to argue with me now: "&lt;em&gt;typescript has &lt;strong&gt;union type&lt;/strong&gt; and also &lt;strong&gt;intersection type&lt;/strong&gt; which a variable can be assigned to several types! You are wrong Lucas!&lt;/em&gt;" Yes, you are right about union and intersection type, but this is just one way to think of the types, and I prefer to think of the types in typescript as &lt;strong&gt;a set of possible values.&lt;/strong&gt; For instance, a number type is a set of all number values. &lt;em&gt;2, 45, 1000&lt;/em&gt; belongs to it, but &lt;em&gt;'book', 'student'&lt;/em&gt; not. And depends on the &lt;a href="https://www.typescriptlang.org/tsconfig#strictNullChecks"&gt;strictNullChecks&lt;/a&gt; setting, null and undefined may or may not be part of the set. (If the strictNullChecks is turned off, null and undefined are permissible values in every type.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Type Alias
&lt;/h2&gt;

&lt;p&gt;The smallest type set is an empty set, which is an empty domain, no value can be found in it. It's also known as &lt;strong&gt;Never&lt;/strong&gt; type in typescript, no values are assignable to a never type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const A:never = 'a' // Error. Type 'string' is not assignable to type 'never'.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next smallest type set contains a single value. There is only one single value that can be found in this domain, which &lt;br&gt;
corresponds to typescript &lt;strong&gt;literal type&lt;/strong&gt;, also known as &lt;strong&gt;unit type&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type A = 'a'
type B = 'b'
type One = 1

const category:A = 'a' // Correct
const category:A = 'b' // Error, Type '"b"' is not assignable to type '"a"'.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to form two or three values, you can use union unit types, which corresponds to typescript union type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type AB = 'a' | 'b'
const A: AB = 'a' // Correct
const B: AB = 'b' // Correct
const C: AB = 'c' // Type '"c"' is not assignable to type 'AB'.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The values in these sets of values or domains are finite, it's quite easy to reason with. But most of time the domain we are dealing with is infinite, such as string, number or an interface, yet we still can think of them as a set of values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type num = 1 | 2 | 3 | 4 | ... 
type str = 'apple' | 'banana' | 'book' | ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The number type is the set of values of all the numbers in the universe, and the string type is the set of values of all the strings in the universe. &lt;/p&gt;

&lt;h2&gt;
  
  
  What does assignable mean?
&lt;/h2&gt;

&lt;p&gt;How can this mindset help us understand better the Typescript's type system? I don't know if you ever encountered a situation when Typescript jumps out an error and it says: &lt;em&gt;Type A is not assignable to type B&lt;/em&gt; , and I am like: &lt;em&gt;What? the type A definitely can assign to type B.&lt;/em&gt; This misunderstanding is because I didn't fully understand what typescript was trying to tell me. Here is a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Fruit = 'apple' | 'banana'
const log = (str:Fruit) =&amp;gt;  {
    console.log(str)
}

let myFruit = 'apple'

log(myFruit) // Error. Argument of type 'string' is not assignable to parameter of type 'Fruit'.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First of all, you may ask why a string is not assignable to type 'Fruit' which is also a string, 'apple' or 'banana'. The word &lt;strong&gt;&lt;em&gt;'assignable'&lt;/em&gt;&lt;/strong&gt; appears in many Typescript errors, in the context of set of values, it means either 'member of' or 'subset of'. So now we can translate the error message to &lt;em&gt;Argument of type 'string' is not a member of (subset of) parameter of type 'Fruit'.&lt;/em&gt;  If you are still asking is string a subset of type 'Fruit' or is type 'Fruit' a subset of string? You should think of types as a set of values. In the domain of string type contains infinite string values, on the other hand the type 'Fruit' only contains two values, 'apple' and 'banana'. So clearly type 'Fruit' is a subset of string, or string is the superset of type 'Fruit'. Now the error message makes sense to us, of course the string is not assignable to type 'Fruit'.&lt;/p&gt;

&lt;p&gt;To fix the error is simple, we just change the keyword &lt;strong&gt;let&lt;/strong&gt; to &lt;strong&gt;const&lt;/strong&gt; , so Typescript will know the value 'apple' won't change in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interface
&lt;/h2&gt;

&lt;p&gt;Now let's take a look at the Typescript interface. Let's say we have two interfaces&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface AB {
  a:string
  b: string
}

interface ABC {
  a:string
  b: string
  c: string
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now my question is which interface is a subset of (a member of ) or assignable to another? You may immediately think: "interface AB is a subset of interface ABC, because inside interface ABC contains more values." But it's quite the opposite in this case, the correct answer is interface ABC is a subset of interface AB. That's because Javascript is inherently duck typed. And Typescript models this behavior. It means values with additional properties still belong to a type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Person {
  name:string  
}

const person = {
  name:'aa',
  age:21,
  eyeColor:'blue'
}

const personA:Person = person // Correct
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You also can verify it by creating an interface Union type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Person {
  name:string  
}

interface ExtraInfo {
  job: string
  habit:string
  favouriteBook:string
}

type PersonInfo = Person | ExtraInfo

const personaB:PersonInfo = {
  name:'joe',
  job: 'developer',
  habit:'read',
  favouriteBook:'book'
} // Correct
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we know, &lt;strong&gt;&amp;amp;&lt;/strong&gt; operator in Typescript computes the intersection of two types. Interface Person and ExtraInfo don't have common properties, but cause the duck typed behavior, &lt;em&gt;&lt;strong&gt;values with additional properties still belong to a type&lt;/strong&gt;&lt;/em&gt;  So the interface Union type will include all the properties in each interface. And you may surprisingly find an empty interface {} is the super set of all other interfaces, because it means it includes all the possible values. &lt;br&gt;
Back to our first question, I hope you have a clear idea now why the interface ABC is the subset of interface AB.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>CSS Drawing Tips</title>
      <dc:creator>Lucas jin</dc:creator>
      <pubDate>Thu, 18 Nov 2021 09:51:33 +0000</pubDate>
      <link>https://dev.to/one-beyond/css-drawing-tips-eie</link>
      <guid>https://dev.to/one-beyond/css-drawing-tips-eie</guid>
      <description>&lt;p&gt;Have you heard of &lt;a href="https://cssbattle.dev/" rel="noopener noreferrer"&gt;cssBattle&lt;/a&gt;? It's a website that provides some simple shape drawings, where  the user should use minimal  css code to recreate it. Recently  I have completed all 80 drawings, and I think I can share some css drawing techniques here. Learning these techniques may not be very helpful for your daily coding work life, but you may at least find some fun in css.&lt;/p&gt;

&lt;p&gt;First things first, here are some techniques that I often used during these 80 challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/background" rel="noopener noreferrer"&gt;background&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/border" rel="noopener noreferrer"&gt;border&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius" rel="noopener noreferrer"&gt;border-radius&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow" rel="noopener noreferrer"&gt;box-shadow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/drop-shadow()" rel="noopener noreferrer"&gt;drop-shadow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path" rel="noopener noreferrer"&gt;clip-path&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-box-reflect" rel="noopener noreferrer"&gt;-webkit-box-reflect&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When I open a new challenge, before starting to write any css, first of all I analyse the original drawing, let's take this &lt;a href="https://cssbattle.dev/play/52" rel="noopener noreferrer"&gt;challenge No.52&lt;/a&gt; as an example. As I am looking at this, I can tell that there are only two shapes in this drawing, which is a circle and a rectangle, I am then thinking that do these shapes have the same angle and equal proportion, because we can only increase or decrease the size by using box-shadow and we can't change the box-shadow’s angle individually. And yes, the circle's angle doesn't really matter, and all the rectangles have the same angle and the same size. So in this case I can easily use box-shadow to recreate the shapes.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94sys880jcohmitobwj9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94sys880jcohmitobwj9.png" alt="No.52 challenge"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's try it.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/lucas1004jx/embed/WNEJyxe?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;From the code example above, you can see that I only use one div to create all the circles using the css &lt;code&gt;box-shadow&lt;/code&gt; property. And for the rectangle we can do the same, first we create a rectangle as our base, from which we recreate the other rectangles using box-shadow. &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/lucas1004jx/embed/qBXYKxY?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;And that's it, we have completed our challenge. I use pseudo class &lt;code&gt;:before&lt;/code&gt; here just because I don't want to write another &lt;code&gt;div&lt;/code&gt; tag in the html, but you can use another html tag to create the rectangle.&lt;/p&gt;

&lt;p&gt;Let's see another example using &lt;code&gt;box-shadow&lt;/code&gt; and &lt;code&gt;-webkit-box-reflect&lt;/code&gt; to help us save writing more code. &lt;/p&gt;

&lt;p&gt;This is &lt;a href="https://cssbattle.dev/play/45" rel="noopener noreferrer"&gt;challenge No.45&lt;/a&gt; from css drawing:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7m9xe2ijc34q6ckqdyx7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7m9xe2ijc34q6ckqdyx7.png" alt="No.45 challenge"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The same as the previous example, as I am looking at this drawing, I can tell that it's formed by some rectangles. But because they have two different angles, vertical and horizontal, I have to use two shapes to create them. And also the left and right side is symmetrical, so I only need to create half the drawing, then use &lt;code&gt;-webkit-box-reflect&lt;/code&gt; property to create the other half. So first I created the horizontal ones using box-shadow: &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/lucas1004jx/embed/YzxLjKb?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Then I added the vertical ones:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/lucas1004jx/embed/dyzejKy?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;And you can see that half of the drawing is done, now I only need to add &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

-webkit-box-reflect:right -20px


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Voilà, the challenge is done.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/lucas1004jx/embed/oNedmzE?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
 &lt;/p&gt;

&lt;p&gt;Here is another example that I use the exact same technique to create the drawing (&lt;a href="https://cssbattle.dev/play/66" rel="noopener noreferrer"&gt;challenge No.66&lt;/a&gt;), but in this case you have to focus on the negative space:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/lucas1004jx/embed/eYErxGg?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Let's take another two examples to see how to create shapes with css &lt;code&gt;background&lt;/code&gt; property&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cssbattle.dev/play/6" rel="noopener noreferrer"&gt;Challenge No.6&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/lucas1004jx/embed/vYJjbRQ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cssbattle.dev/play/30" rel="noopener noreferrer"&gt;Challenge No.30&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/lucas1004jx/embed/WNEyvBw?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;As you can see, css &lt;code&gt;background&lt;/code&gt; is a really powerful tool, it can create circles and rectangles at the same time and with different sizes. The only gotcha that we should keep in mind when we use background is that the background property is specified as one or more background layers, separated by commas. And the following layer will be positioned below the previous layer.&lt;/p&gt;

&lt;p&gt;So in challenge No.6 I first drew the background with a transparent circle in it, then I drew the color wheel in the second layer, so we can see the &lt;code&gt;conic-gradient&lt;/code&gt; as a circle in the center. If you mess up with the background layer, you will probably only see the conic-gradient layer take the whole screen, but not the background color nor the circle shape.&lt;/p&gt;

&lt;p&gt;Here is another example that I used background layer to complete the challenge:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cssbattle.dev/play/33" rel="noopener noreferrer"&gt;Challenge No.33&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/lucas1004jx/embed/yLoEYpp?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;box-shadow&lt;/code&gt; and &lt;code&gt;background&lt;/code&gt; are the two most useful properties that I find to help me create the drawings during the challenge. As for the other properties, they are straightforward to use, so I won't explain them with more details here.&lt;/p&gt;

</description>
      <category>css</category>
      <category>cssdrawing</category>
      <category>cssbattle</category>
    </item>
    <item>
      <title>CSS Selector’s priority</title>
      <dc:creator>Lucas jin</dc:creator>
      <pubDate>Tue, 02 Nov 2021 08:26:24 +0000</pubDate>
      <link>https://dev.to/one-beyond/css-selectors-priority-1cjh</link>
      <guid>https://dev.to/one-beyond/css-selectors-priority-1cjh</guid>
      <description>&lt;p&gt;Almost all the CSS style conflicts and style overrides have to do with the css selector's priority. In this article I will talk about how the css selector's priority works.&lt;/p&gt;

&lt;p&gt;CSS selectors have a strict hierarchy. I have divided them into 6 levels (from 0 to 5).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Level 0 :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors"&gt;Universal selector&lt;/a&gt; &lt;code&gt;*&lt;/code&gt;

 &lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors#combinators"&gt;CSS combinators&lt;/a&gt;, such as adjacent sibling selector &lt;code&gt;+&lt;/code&gt;, child selector &lt;code&gt;&amp;gt;&lt;/code&gt;, general sibling selector &lt;code&gt;~&lt;/code&gt;, descendant selector &lt;code&gt;space&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;underline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;18px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes"&gt;Logic pseudo-class&lt;/a&gt;, such as &lt;code&gt;:not()&lt;/code&gt;, &lt;code&gt;:is()&lt;/code&gt;, &lt;code&gt;:where()&lt;/code&gt; , these logic pseudo classes won't affect the priority, what will affect the priority is the selectors that pass to the pseudo-class function. Pay attention that here I only list the logic pseudo class, not including the other non-logic pseudo class, such as &lt;code&gt;:hover&lt;/code&gt;, &lt;code&gt;:first-child&lt;/code&gt; etc.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.text&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nd"&gt;:is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="nd"&gt;:where&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;orange&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Level 1:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors"&gt;Type selector&lt;/a&gt;, such as &lt;code&gt;p&lt;/code&gt; &lt;code&gt;div&lt;/code&gt; &lt;code&gt;header&lt;/code&gt; &lt;code&gt;span&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Level 2:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors"&gt;Class selector&lt;/a&gt; &lt;code&gt;.className&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors"&gt;attribute selector&lt;/a&gt; &lt;code&gt;[attribute]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-text&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;blue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes"&gt;pseudo class&lt;/a&gt; such as &lt;code&gt;:hover&lt;/code&gt; &lt;code&gt;:link&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;green&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements"&gt;pseudo-element&lt;/a&gt; such as &lt;code&gt;:first-child:&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:first-child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Level 3&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/ID_selectors"&gt;ID selector&lt;/a&gt; &lt;code&gt;#id&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Level 4&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inline style in html tag:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;style= &lt;/span&gt;&lt;span class="s"&gt;"color:#000"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;some text&lt;span class="nt"&gt;&amp;lt;p/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Level 5&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The key word &lt;code&gt;!important&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key word &lt;code&gt;!important&lt;/code&gt; has the highest priority, usually it’s used to override the javascript style, otherwise I don’t recommend using it, it will be difficult to maintain the code if we abuse the !important key word.&lt;/p&gt;

&lt;p&gt;We can see that from 0 to 3 level is all about css selectors’ priority, it’s also the most important part. If we can fully understand it , it will be much easier for us to override the style using css selector.&lt;/p&gt;

&lt;p&gt;Although now we know all the css selectors’ priority, it’s still very abstract for us to compare them when there are multiple selectors together. You may ask, how can we compare &lt;code&gt;div .foo[bar] { color:#fff }&lt;/code&gt; with &lt;code&gt;body &amp;gt; div p.foo { color: #000 }&lt;/code&gt; ?&lt;/p&gt;

&lt;p&gt;Don’t worry, I’ll also  explain how to calculate the css selectors’ priority with actual values. Let’s say if you encounter one &lt;strong&gt;level 0&lt;/strong&gt; priority selector, then you add &lt;strong&gt;0&lt;/strong&gt; value to the total priority , if you encounter one &lt;strong&gt;level 1&lt;/strong&gt; priority selector, then you add &lt;strong&gt;1&lt;/strong&gt; value to the total priority, if you encounter one &lt;strong&gt;level 2&lt;/strong&gt; priority selector, then you add &lt;strong&gt;10&lt;/strong&gt; value to the total priority, and finally if you encounter one &lt;strong&gt;level 3&lt;/strong&gt; priority selector, you add &lt;strong&gt;100&lt;/strong&gt; value to the total priority. In summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Level 0: &lt;strong&gt;+0&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Level 1: &lt;strong&gt;+1&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Level 2: &lt;strong&gt;+10&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Level 3: &lt;strong&gt;+100&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s see some examples:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;* &amp;gt; div {}&lt;/code&gt; : 1 general selector (&lt;strong&gt;level 0&lt;/strong&gt;), 1 css combinator (&lt;strong&gt;level 0&lt;/strong&gt;), 1 type selector (&lt;strong&gt;level 1&lt;/strong&gt;), so the total value is &lt;strong&gt;0 + 0 + 1 = 1&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;div &amp;gt; p .text:not(.content)&lt;/code&gt;: 2 type selector (&lt;strong&gt;level 1&lt;/strong&gt;), 1 &lt;em&gt;css combinator&lt;/em&gt; (&lt;strong&gt;level 0&lt;/strong&gt;), 2 &lt;em&gt;class selector&lt;/em&gt; (&lt;strong&gt;level 2&lt;/strong&gt;), 1 logic pseudo-class (&lt;strong&gt;level 0&lt;/strong&gt;), so the total value is &lt;strong&gt;2 * 1 + 0 + 2 * 10 + 0 = 22&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;p[content="story"]&lt;/code&gt;: 1 type selector (&lt;strong&gt;level 1&lt;/strong&gt;), 1 attribute selector (&lt;strong&gt;level 2&lt;/strong&gt;), so the total value is &lt;strong&gt;1+ 10 = 11&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;#list &amp;gt; ol&lt;/code&gt;: 1 id selector (&lt;strong&gt;level 3&lt;/strong&gt;), 1 css combinator (&lt;strong&gt;level 0&lt;/strong&gt;), 1 type selector (&lt;strong&gt;level 1&lt;/strong&gt;), so the total value is &lt;strong&gt;100 + 0 + 1 = 101&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s how you calculate the priority value in css. Now you may ask what if I add 11 type selector, then the value is 11, so can it override one class selector, which has a value 10 ? The truth is the value here is only symbolic, I use 1, 10 ,100 here because no one will really use 10 selectors in the code, and the real fact is that the lower priority level selector can’t ever override the higher priority level. So even if you have 100 type selectors, you can’t override even one class selector.&lt;/p&gt;

&lt;p&gt;If you happen to write 2 sets of selectors to target one element, and they have the same priority value, then the subsequent selectors will override the previous one. That’s how css is rendered in the web.&lt;/p&gt;

&lt;p&gt;And that’s all you have to know about the css selectors’ priority.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>html</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
