Typescript接口可选方法属性未定义

时间:2017-11-11 15:48:02

标签: typescript interface

我在关于深度打字稿的Pluralsites课程之后。使用接口时,我有以下内容:

nsubj(saw-2, John-1)
root(ROOT-0, saw-2)
dobj(saw-2, Mary-3)
case(telescope-6, with-4)
det(telescope-6, a-5)
nmod(saw-2, telescope-6)

我现在宣布一本书如下:

interface Book {
    id: number;
    title: string;
    author: string;
    available: boolean;
    category: Category;
    pages: number;
    markDamaged: DamageLogger;
}

interface DamageLogger {
    (reason: string): void;
}

一切都很顺利,但只要我将markDamaged的界面更改为可选项,如下所示:

let myBook: Book = {
    id: 5,
    title: 'Pride and Prejudice',
    author: 'Jane Austen',
    available: true,
    category: Category.Fiction,
    pages: 250,
    markDamaged: (reason: string) => console.log('Damaged: ' + reason)
};

myBook.markDamaged('missing back cover');

编译器在这一行上咆哮:

interface Book {
    id: number;
    title: string;
    author: string;
    available: boolean;
    category: Category;
    pages: number;
    markDamaged?: DamageLogger;
}

并说markDamaged属性可能未定义。我删除了问号,一切都很好。

这里有什么想法吗?我在课程的其他地方使用了可选参数,没有任何问题,但在使用界面时,这就是我所看到的。

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

那是因为它不能保证被定义。首先检查它,编译器应该停止抱怨。

if (myBook && myBook.markDamaged) {
    myBook.markDamaged('missing back cover');
}

答案 1 :(得分:0)

如果您说明markDamaged?: DamageLogger,则表示Book可能拥有markDamaged属性,也可能没有Book属性。然后,编译器强制您检查myBook(包括markDamaged)实际上是否有--strictNullChecks,然后才能让您调用它。仅在设置interface Book { markDamaged: DamageLogger } interface DamageLogger { (reason: string): void } let myBook: Book = { markDamaged: (reason: string) => console.log('Damaged: ' + reason) } // myBook: Book; it definitely has markDamaged myBook.markDamaged('missing back cover') 编译器选项时才启用此检查。

这有效

interface Book { markDamaged?: DamageLogger }
// ...
// myBook: Book; Books do not definitely have markDamaged
myBook.markDamaged('...')

这不是

if(myBook.markDamaged) {
    // Now we know it's there, we can call it
    myBook.markDamaged('...')
}

但是这样做

interface Book { markDamaged?: DamageLogger }
// don't say it's a Book
// inferred: myBook: { markDamaged: (reason: String) => void }
// TypeScript's type system is structural, not nominal
// The identity of a type is in it's structure, not name
// myBook's type says that it definitely has markDamaged
let myBook = { markDamaged: (reason: String) => console.log('Damaged: ' + reason) }
myBook.markDamaged('...')

function read(b: Book) {}
// myBook's type is a subtype of Book, because a Book can be missing markDamaged but myBook definitely has it.
read(myBook)

这也有效:

import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.koushik.javabrains.messenger.model.Message;
import org.koushik.javabrains.messenger.service.MessageService;



@Path("/messages")
public class MessageResource {
    MessageService messageService = new MessageService();
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<Message> getMessages(){
        System.out.println("Hello There");
        List<Message> returnedList = messageService.getAllMessages();
        System.out.println(returnedList);
        return returnedList;
    }
    @GET
    @Path("/{messageId}")
    @Produces(MediaType.APPLICATION_JSON)
    public Message getMessage(@PathParam("messageId") long messageId){

        System.out.println("Message returned");
        return messageService.getMessage(messageId);

    }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public Message addMessage(Message message){
        return messageService.addMessage(message);
    }

    @PUT
    @Path("/{messageId}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Message updateMessage(@PathParam("messageId") long id , Message message){
        message.setId(id);
        return messageService.updateMessage(message);
    }

    @DELETE
    @Path("/messageId")
    @Produces(MediaType.APPLICATION_JSON)
    public void deleteMessage(@PathParam("messageId") long id){
        System.out.println("Hello There");
        messageService.removeMessage(id);
    }
}






package org.koushik.javabrains.messenger.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.koushik.javabrains.messenger.database.DatabaseClass;
import org.koushik.javabrains.messenger.model.Message;

public class MessageService {

    private Map<Long , Message> messages = DatabaseClass.getMessages();

    public MessageService(){

        messages.put(1L, new Message(1, "Hello World" , "koushik"));
        messages.put(2L, new Message(2, "Hello Jersey" , "Koushik"));

    }

    public List<Message> getAllMessages(){

        return new ArrayList<Message>(messages.values());
    }

    public Message getMessage(long id){
        Message m = messages.get(id);
        System.out.println("Value of message "+m);
        return m;
    }

    public Message addMessage(Message message){

        message.setId(messages.size()+1);
        messages.put(message.getId(), message);
        return message;
    }

    public Message updateMessage(Message message){

        if(message.getId() <=0){
            return null;
        }
        messages.put(message.getId(), message);
        return message;
    }

    public Message removeMessage(long id){
        return messages.remove(id);
    }
}






package org.koushik.javabrains.messenger.database;

import java.util.HashMap;
import java.util.Map;

import org.koushik.javabrains.messenger.model.Message;
import org.koushik.javabrains.messenger.model.Profile;

public class DatabaseClass {

    private static Map<Long , Message> messages = new HashMap();

    private static Map<String , Profile> profiles = new HashMap();

    public static Map<Long , Message> getMessages() {

        return messages;
    }

    public static Map<String, Profile> getProfiles() {
        return profiles;
    }

}